自React 16.8支持hook以来,RN也在0.59版本支持了hook,而且官方给出的组件实例也分为了class和hook两个版本,可以遇见hook是未来的趋势。恰巧最近重构RN项目,把最近遇到的问题和思考记录一下。

今天是总结课。
重构,我想这个词可能没有多少人愿意做,在业务迭代频繁的今天,重构意味着资源的消耗,而且承担着未知的风险,那么为什么还要重构?
主要有以下思考:
hook化一个很重要的就是class逻辑的复用,比如:
- // class
 - this.setState({
 - count:0
 - },()=>{
 - // 修改数据成功之后 处理的逻辑
 - })
 - // hook
 - useEffect(()=>{
 - // 监控count值的变更 处理逻辑
 - },[count])
 
如果我们需要监控的值很多,是否需要写很多useEffect呢?这里会用到另一个概念,细粒度组件。写hook写多了,会把一些需要处理的业务组件都抽离出来,每个组件只管自己的状态。这样就会极大减少了父组件的业务堆积和state堆积。
组件多了就会涉及到组件传值,这里有三种场景:
props传值,通过标签属性传递。
- // props 通过标签传值
 - //
 - export default CenterMenu(props){
 - const { style, list } = props;
 - //. ...
 - }
 
context包裹的话,就会把所有状态都放在了父组件,就会造成context很臃肿。
- value={{
 - serviceBill,
 - patientInfo,
 - batchList,
 - navigation,
 - ...params
 - }}>
 - // ...View
 - //
 - const Footer = () => {
 - const data = useContext(PerfectInfoContext);
 - // ...
 - }
 - export default Footer;
 
用context包裹一个Reducer,再用memo缓存,我们就可以在其他函数组件中去触发状态变更。
- const initState={
 - isLoading: true,
 - isSignOut: false,
 - userToken: null,
 - routes
 - }
 - const reducer=(prevState, action)=>{ // switch}
 - const [state, dispatch] = useReducer(reducer, initState);
 - const authContextProps=(dispatch)=>{
 - return {
 - signIn:async()=>{ // dispatch },
 - signOut:async()=>{ // dispatch}
 - }
 - }
 - const authContextData = useMemo(authContextProps(dispatch), []);
 - return (
 - // view
 - );
 - // 其他函数组件
 - const { signOut } = useContext(AuthContext);
 
细粒度的话,ref应该是一个很好的选择,拿输入框组件举例:
- function FancyInput(props, ref) {
 - const inputRef = useRef(null);
 - // 暴露给父组件使用
 - useImperativeHandle(ref, () => ({
 - focus: () => {
 - inputRef.current.focus();
 - }
 - // 其他方法也可以或者state
 - }));
 - return ;
 - }
 - export default forwardRef(FancyInput);
 - // 父组件
 - const fancyRef = useRef(null);
 - // useEffect、 onPress中使用
 - const onPress=()=>{
 - fancyRef.current?.focus()
 - }
 
灵活的路由配置也是我们重构要考虑的一部分,怎么在RN中实现vue项目的路由配置呢?这需要借助React Navigation 5.x以上版本的Stack。比较可惜的是4.x的 NavigationEvents组件被移除。
- // 4.x可使用 4.x之后被移除
 - onWillFocus={payload => console.log('will focus', payload)}
 - onDidFocus={payload => console.log('did focus', payload)}
 - onWillBlur={payload => console.log('will blur', payload)}
 - onDidBlur={payload => console.log('did blur', payload)}
 - />
 - {/* Your view code */}
 
5.x版本有点仓促,已不在维护,变更较大,核心代码分为native、stack等,可以单独使用。现在的版本6.x大部分api都做了变更,不推荐单独升级。
- // 屏幕事件focus、blur、beforeRemove、state
 - React.useEffect(() => {
 - const unsubscribe = navigation.addListener('focus', () => {
 - // do something
 - });
 - return unsubscribe;
 - }, [navigation]);
 
回到路由配置上,我们可以通过routes来控制路由变化:
- // 路由配置
 - export const routes = [
 - ...roleRouters,
 - {
 - name: 'Home',
 - screen: HomeScreen,
 - hidden: false,
 - options: {},
 - },
 - ...personRouters,
 - ...ordersRouters,
 - ...goodsRouters,
 - ...customerRouters,
 - ...taskRouters,
 - ...otherRouters,
 - ];
 - {state.userToken == null ? (
 - name='Login'
 - component={LoginScreen}/>) :
 - (state.routes.map((e, i) => {
 - if (!e.hidden) {
 - return (
 - key={i.toString()}
 - name={e.name}
 - params={e.params}
 - component={e.screen}/>
 - );
 - }})
 - )}
 - {/* 公共路由 无论是否登录都可以访问 */}
 - {commonRoutes.map((e, i) =>
 )} 
如果你觉得import导入太多的话,navigation也提供了支持,你也可以动态导入:
- // 动态导入
 - export const routes = [
 - {
 - name: 'Home',
 - getComponent: () => require('@/pages/other/cmsWeb').default,
 - options: { header: () => {} },
 - },
 - ];
 - state.routes.map(
 - (e, i) =>
 ; - )
 
navigation提供了一个辅助效果,回到顶部:
- import * as React from 'react';
 - import { ScrollView } from 'react-native';
 - import { useScrollToTop } from '@react-navigation/native';
 - function Albums() {
 - const ref = React.useRef(null);
 - useScrollToTop(ref); // ScrollView或者FlatList
 - return
 {/* content */} ;- }
 
除了babel、eslint配置外,就是模块化的管理,路由模块化、页面模块化、api模块化。工具方法、共用组件、公共hook、公共资源、本地常量,以及屏幕适配方案,剩下就是规范统一,这样一个小中项目基本就可以hold住了。
hook之前都停留着概念上,这次的落地能发现一些问题,也能跟贴切与class对比,目前还是粗浅使用,更加复杂的场景还待处理。
补充一点就是,在RN中require的本地图片返回的是一个id,那么我们有集中处理必要了。
                网页标题:让我一起聊聊Hook使用总结
                
                转载源于:http://www.csdahua.cn/qtweb/news36/326386.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网