IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    2个奇怪的React写法

    卡颂发表于 2023-03-14 09:23:50
    love 0

    大家好,我卡颂。

    虽然React官网用大量篇幅介绍最佳实践,但因JSX语法的灵活性,所以总是会出现奇奇怪怪的React写法。

    本文介绍2种奇怪(但在某些场景下有意义)的React写法。也欢迎大家在评论区讨论你遇到过的奇怪写法。

    欢迎加入人类高质量前端交流群,带飞

    ref的奇怪用法

    这是一段初看让人很困惑的代码:

    function App() {
      const [dom, setDOM] = useState(null);
     
      return <div ref={setDOM}></div>;
    }

    让我们来分析下它的作用。

    首先,ref有两种形式(曾经有3种):

    1. 形如{current: T}的数据结构
    2. 回调函数形式,会在ref更新、销毁时触发

    例子中的setDOM是useState的dispatch方法,也有两种调用形式:

    1. 直接传递更新后的值,比如setDOM(xxx)
    2. 传递更新状态的方法,比如setDOM(oldDOM => return /* 一些处理逻辑 */)

    在例子中,虽然反常,但ref的第二种形式和dispatch的第二种形式确实是契合的。

    也就是说,在例子中传递给ref的setDOM方法,会在div对应DOM更新、销毁时执行,那么dom状态中保存的就是div对应DOM的最新值。

    这么做一定程度上实现了感知DOM的实时变化,这是单纯使用ref无法具有的能力。

    useMemo的奇怪用法

    通常我们认为useMemo用来缓存变量props,useCallback用来缓存函数props。

    但在实际项目中,如果想通过缓存props的方式达到子组件性能优化的目的,需要同时保证:

    • 所有传给子组件的props的引用都不变(比如通过useMemo)
    • 子组件使用React.memo

    类似这样:

    function App({todos, tab}) {
        const visibleTodos = useMemo(
          () => filterTodos(todos, tab),
        [todos, tab]);
        
        return <Todo data={visibleTodos}/>;
    }
    
    // 为了达到Todo性能优化的目的
    const Todo = React.memo(({data}) => {
      // ...省略逻辑
    })

    既然useMemo可以缓存变量,为什么不直接缓存组件的返回值呢?类似这样:

    function App({todos, tab}) {
      const visibleTodos = useMemo(
          () => filterTodos(todos, tab),
      [todos, tab]);
      
      return useMemo(() => <Todo data={visibleTodos}/>, [visibleTodos])
    }
    
    function Todo({data}) {
      return <p>{data}</p>;
    }

    如此,需要性能优化的子组件不再需要手动包裹React.memo,只有当useMemo依赖变化后子组件才会重新render。

    总结

    除了这两种奇怪的写法外,你还遇到哪些奇怪的React写法呢?



沪ICP备19023445号-2号
友情链接