关于Hooks的思考

258 阅读3分钟

为什么说hooks复用逻辑的方式,要比render prop和封装高阶组件要好?

我们经常有哪些逻辑需要复用

  1. 在生命周期中的副作用函数。例如监听事件

    componenDidMount () {
      window.addEventListener('scroll', handler)
    }
    
  2. 复用生命周期和状态。例如在生命周期内请求数据并且设置状态

    state = { list: [] }
    async componenDidMount () {
      const list = await fetch();
      this.setState({
        list
      })
    }
    
  3. 复用逻辑逻辑和状态。

    state = { status: false };
    handleStatus () {
      const newStatus = complexHandle(state);
      this.setState({
        status: newStatus
      })
    }
    // 其中state和handleStatus是公用逻辑
    
  4. 最极端的情况,复用逻辑,生命周期和状态。

现有的逻辑复用方案

  1. Mixin(混入) vue和react都使用过这样的策略

    • 功能:

      从vue的角度来说,因为我用react的时候,mixin的方式已经消失了。 O(∩_∩)O哈哈~。 vue中的Mixin可以混入状态,生命周期,和处理逻辑。可以覆盖我们的所有场景。

    • 缺点:

      1. 对组件的侵入性太强, vue是用mixin的时候,无论是混入的状态和方法还是组件上定义的状态和方法,都是相同的访问方式,使用者根本无法分辨出当前组件的方法是来自混入的还是组件自定义的。
      2. 用法无法知晓当前混入的方法和属性,除非去查看mixin文件。一般编辑器也不会自动提示。
      3. 尤其混入不止一个mixin的时候,谁用谁爽。
  2. 高阶组件的方式

    • 缺点

      1. 对组件也有一定的侵入性, 一般高阶组件在会通过给子组件传入props来注入属性或者方法,那么就要求,你子组件的定义的接口,不能和高阶组件注入的相同。
  3. 需要处理静态属性和方法。

  4. 同样无法区分调用props.methods的方法来自高阶组件还是祖父组件传入的。

  5. render prop的方式

    待补充

hooks复用逻辑的优点

hooks复用逻辑的方式

hooks主要是通过自定义hooks来复用逻辑。

hooks复用逻辑的优点

  1. 对组件几乎无侵入性。

  2. 在组件内,可以清晰的看到复用的逻辑和状态。

  3. 更加灵活

  4. 函数更加方便测试

    
    function useDemo () {
       const [ count, setCount ] = useState(0);
    
       useEffect(() => {
           console.log('count');
       }, [count]);
    
       useEffect(() => {
          console.log('mounted');
       }, [])
       const handler = useCallback(
           () => {
               setCount(count + 10)
           },
           [count]
       )
       return { count, handler };
    }
    
    function Hello () {
       const { count, handler } = useDemo(); 
       return <div onClick={handler}> count: { count } </div>
    }
    

hooks目前的不足

  1. 依赖需要用户手动传入,如果依赖传入不正确或者没有传入,可能会导致执行逻辑出现错误。

    官方说,以后依靠编辑器的自动补充功能,似乎不能从源码的层面解决

    例如:

      const [ count, setCount ] = useState(0);
      useEffect(() => {
            console.log('count');
      // 如果在依赖中不指定count依赖项,那么这个副作用函数,会在每次render的时候执行
      // 这有时候不符合我们的预期
      }, [count]);
    
    
  2. hooks目前还不能完全替代类,例如 componentDidCatchandgetDerivedStateFromError`:目前还没有这些方法的 Hook 等价写法。 但是可以实现大部分的业务场景。