如何通过React Hook优化四种组件实现长尾关键词效果?

2026-03-31 17:251阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2211个文字,预计阅读时间需要9分钟。

如何通过React Hook优化四种组件实现长尾关键词效果?

目录+前言+组件抽取+memo+优化组件+React.memo+语法+useCallback+优化组件+useCallback+用途+useMemo+优化+语法+useCallback和useMemo+区别+前言+React Hook+已成为当前最流行的开发模式+React 16.8+以来

目录
  • 前言
  • 组件抽取
  • memo 优化组件
    • React.memo 语法
  • useCallback 优化组件
    • useCallback 作用
  • useMemo 优化
    • useMemo 语法
  • useCallback 和 useMemo 区别

    前言

    React Hook 已成为当前最流行的开发范式,React 16.8 以后基于 Hook 开发极大简化开发者效率,同时不正确的使用 React Hook也带来了很多的性能问题,本文梳理基于 React Hook 开发组件的过程中如何提高性能。

    组件抽取

    优化前

    每次点击Increase都会引起子组件Child的渲染,哪怕子组件并没有状态变化

    function Before(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     let [name,setName] = useState('-')     const handleClick = ()=>{         setCount(count+1)     }     const handleInput = (e)=>{         setName(e.target.value)     }     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" onChange={handleInput}/>             </div>             <hr />             <Child name={name}/>         </div>     ) } // 子组件 function Child(props){     console.log('Demo1 Child')     return (         <div className='l50'>             子组件渲染:{props.name}         </div>     ) }

    优化后

    只需要把Increase抽取成独立的组件即可。此时点击按钮,子组件并不会渲染。

    /**  * 优化后,Increase提取以后,上下文发生变化,组件内  * @returns   */ function Increase(){     console.log('Child Increase')     let [count,setCount] = useState(0)     const handleClick = ()=>{         setCount(count+1)     }     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>         </div>     ) } function After(){     console.log('Demo1 Parent')     let [name,setName] = useState('-')     const handleInput = (e)=>{         setName(e.target.value)     }     return (         <div>             <Increase/>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" onChange={handleInput}/>             </div>             <Child name={name}/>         </div>     ) } // 子组件 function Child(props){     console.log('Demo1 Child')     return (         <div className='l50'>             子组件渲染:{props.name}         </div>     ) }

    memo 优化组件

    同样基于上述优化前代码,如果不抽取组件,使用memo优化后,当点击按钮后,也不会触发二次渲染。

    // 优化前 function AfterMemo(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     let [name,setName] = useState('-')     const handleClick = ()=>{         setCount(count+1)     }     const handleInput = (e)=>{         setName(e.target.value)     }     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" onChange={handleInput}/>             </div>             <Child name={name}/>         </div>     ) } // 子组件 const Child = memo((props)=>{     console.log('Demo1 Child')     return (         <div className='l50'>             子组件渲染:{props.name}         </div>     ) })

    React.memo 语法

    React.memo 为高阶组件,与 React.PureComponent相似。

    function TestComponent(props){   // 使用 props 渲染 } function areEqual(prevProps,nextProps){   /*   如果把 nextProps 传入 render 方法的返回结果与   将 prevProps 传入 render 方法的返回结果一致则返回 true,   否则返回 false   */ } export default React.memo(TestComponent,areEqual)

    与 class 组件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,areEqual 会返回 true;如果 props 不相等,则返回 false。这与 shouldComponentUpdate 方法的返回值相反。

    useCallback 优化组件

    如果已经用了memo,当遇到下面这种场景时,同样会触发子组件渲染。比如,给Child绑定一个handleClick,子组件内部增加一个按钮,当点击子组件的按钮时,更改count值,即使没有发生name变化,也同样会触发子组件渲染,为什么?memo不是会判断name变化了,才会更新吗?

    function Before(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     let [name,setName] = useState('-')     const handleClick = ()=>{         setCount(count+1)     }     const handleInput = (e)=>{         setName(e.target.value)     }     const handleChange = ()=>{         setCount(count+1)     }     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" onChange={handleInput}/>             </div>             <Child name={name} handleClick={handleChange}/>         </div>     ) } // 子组件 const Child = memo((props)=>{     console.log('Demo1 Child')     return (         <div className='l50'>             子组件渲染:{props.name}             <button onClick={props.handleClick}>更改count</button>         </div>     ) })

    并不是memo没有生效,是因为当状态发生变化时,父组件会从新执行,导致从新创建了新的handleChange函数,而handleChange的变化导致了子组件的再次渲染。

    优化后

    点击父组件的Increase按钮,更改了count值,经过useCallback包裹handleChange函数以后,我们会发现子组件不再渲染,说明每当父组件执行的时候,并没有创建新的handleChange函数,这就是通过useCallback优化后的效果。 即使我们点击子组件的按钮,也同样不会触发子组件的渲染,同样count会进行累加。

    function After(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     let text = useRef();     let [name,setName] = useState('-')     const handleClick = ()=>{         setCount(count+1)     }     const handleInput = (e)=>{         setName(e.target.value)     }     const handleChange = useCallback(()=>{         // 为了让 count 能够累加,我们使用ref 获取值         let val = parseInt(text.current.textContent);         setCount(val+1)     },[])     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10' ref={text}>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" value={name} onChange={handleInput}/>             </div>             <Child name={name} handleClick={handleChange}/>         </div>     ) }

    useCallback 作用

    // 用法 useCallback(()=>{   // to-do },[]) // 示例 function App(){   // 点击按钮调用此函数,但返回被缓存   const onClick = useCallback(() => {     console.log('我被缓存了,怎么点击都返回一样');   }, []);   return (      <button onClick={onClick}>点击</button>   ); }

    • useCallback接收 2 个参数,第一个为缓存的函数,第二个为依赖值
    • 主要用于缓存函数,第二次会返回同样的结果。

    useMemo 优化

    我们定义了一个total函数,内部使用 1 填充了100次,通过reduce计算总和,经过测试发现点击Increase按钮后,只会执行total1,不会执行total2,假设total计算量巨大,就会造成内存的浪费,通过useMemo可以帮我们缓存计算值。

    function Before(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     const handleClick = ()=>{         setCount(count+1)     }     const total1 = ()=>{         console.log('计算求和1')         let arr = Array.from({ length:100 }).fill(1)         return arr.reduce((prev,next)=>prev+next,0)     }     // 缓存对象值     const total2 = useMemo(()=>{         console.log('计算求和2')         let arr = Array.from({ length:100 }).fill(1)         return arr.reduce((prev,next)=>prev+next,0)     },[count])     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div>                 <label>总和:</label>                 <span>{total1()}</span>                 <span>{total2}</span>             </div>         </div>     ) }

    如何通过React Hook优化四种组件实现长尾关键词效果?

    useMemo 语法

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

    • 传入一个函数进去,会返回一个memoized值,需要注意的是,函数内必须有返回值
    • 第二个参数会依赖值,当依赖值更新时,会从新计算。

    useCallback 和 useMemo 区别

    他们都用于缓存,useCallback主要用于缓存函数,返回一个 缓存后 函数,而useMemo主要用于缓存值,返回一个缓存后的值。

    到此这篇关于React Hook 四种组件优化总结的文章就介绍到这了,更多相关React Hook 组件优化内容请搜索易盾网络以前的文章或继续浏览下面的相关文章希望大家以后多多支持易盾网络!

    本文共计2211个文字,预计阅读时间需要9分钟。

    如何通过React Hook优化四种组件实现长尾关键词效果?

    目录+前言+组件抽取+memo+优化组件+React.memo+语法+useCallback+优化组件+useCallback+用途+useMemo+优化+语法+useCallback和useMemo+区别+前言+React Hook+已成为当前最流行的开发模式+React 16.8+以来

    目录
    • 前言
    • 组件抽取
    • memo 优化组件
      • React.memo 语法
    • useCallback 优化组件
      • useCallback 作用
    • useMemo 优化
      • useMemo 语法
    • useCallback 和 useMemo 区别

      前言

      React Hook 已成为当前最流行的开发范式,React 16.8 以后基于 Hook 开发极大简化开发者效率,同时不正确的使用 React Hook也带来了很多的性能问题,本文梳理基于 React Hook 开发组件的过程中如何提高性能。

      组件抽取

      优化前

      每次点击Increase都会引起子组件Child的渲染,哪怕子组件并没有状态变化

      function Before(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     let [name,setName] = useState('-')     const handleClick = ()=>{         setCount(count+1)     }     const handleInput = (e)=>{         setName(e.target.value)     }     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" onChange={handleInput}/>             </div>             <hr />             <Child name={name}/>         </div>     ) } // 子组件 function Child(props){     console.log('Demo1 Child')     return (         <div className='l50'>             子组件渲染:{props.name}         </div>     ) }

      优化后

      只需要把Increase抽取成独立的组件即可。此时点击按钮,子组件并不会渲染。

      /**  * 优化后,Increase提取以后,上下文发生变化,组件内  * @returns   */ function Increase(){     console.log('Child Increase')     let [count,setCount] = useState(0)     const handleClick = ()=>{         setCount(count+1)     }     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>         </div>     ) } function After(){     console.log('Demo1 Parent')     let [name,setName] = useState('-')     const handleInput = (e)=>{         setName(e.target.value)     }     return (         <div>             <Increase/>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" onChange={handleInput}/>             </div>             <Child name={name}/>         </div>     ) } // 子组件 function Child(props){     console.log('Demo1 Child')     return (         <div className='l50'>             子组件渲染:{props.name}         </div>     ) }

      memo 优化组件

      同样基于上述优化前代码,如果不抽取组件,使用memo优化后,当点击按钮后,也不会触发二次渲染。

      // 优化前 function AfterMemo(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     let [name,setName] = useState('-')     const handleClick = ()=>{         setCount(count+1)     }     const handleInput = (e)=>{         setName(e.target.value)     }     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" onChange={handleInput}/>             </div>             <Child name={name}/>         </div>     ) } // 子组件 const Child = memo((props)=>{     console.log('Demo1 Child')     return (         <div className='l50'>             子组件渲染:{props.name}         </div>     ) })

      React.memo 语法

      React.memo 为高阶组件,与 React.PureComponent相似。

      function TestComponent(props){   // 使用 props 渲染 } function areEqual(prevProps,nextProps){   /*   如果把 nextProps 传入 render 方法的返回结果与   将 prevProps 传入 render 方法的返回结果一致则返回 true,   否则返回 false   */ } export default React.memo(TestComponent,areEqual)

      与 class 组件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,areEqual 会返回 true;如果 props 不相等,则返回 false。这与 shouldComponentUpdate 方法的返回值相反。

      useCallback 优化组件

      如果已经用了memo,当遇到下面这种场景时,同样会触发子组件渲染。比如,给Child绑定一个handleClick,子组件内部增加一个按钮,当点击子组件的按钮时,更改count值,即使没有发生name变化,也同样会触发子组件渲染,为什么?memo不是会判断name变化了,才会更新吗?

      function Before(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     let [name,setName] = useState('-')     const handleClick = ()=>{         setCount(count+1)     }     const handleInput = (e)=>{         setName(e.target.value)     }     const handleChange = ()=>{         setCount(count+1)     }     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" onChange={handleInput}/>             </div>             <Child name={name} handleClick={handleChange}/>         </div>     ) } // 子组件 const Child = memo((props)=>{     console.log('Demo1 Child')     return (         <div className='l50'>             子组件渲染:{props.name}             <button onClick={props.handleClick}>更改count</button>         </div>     ) })

      并不是memo没有生效,是因为当状态发生变化时,父组件会从新执行,导致从新创建了新的handleChange函数,而handleChange的变化导致了子组件的再次渲染。

      优化后

      点击父组件的Increase按钮,更改了count值,经过useCallback包裹handleChange函数以后,我们会发现子组件不再渲染,说明每当父组件执行的时候,并没有创建新的handleChange函数,这就是通过useCallback优化后的效果。 即使我们点击子组件的按钮,也同样不会触发子组件的渲染,同样count会进行累加。

      function After(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     let text = useRef();     let [name,setName] = useState('-')     const handleClick = ()=>{         setCount(count+1)     }     const handleInput = (e)=>{         setName(e.target.value)     }     const handleChange = useCallback(()=>{         // 为了让 count 能够累加,我们使用ref 获取值         let val = parseInt(text.current.textContent);         setCount(val+1)     },[])     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10' ref={text}>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div className='l50'>                 <label htmlFor="">改变子组件:</label>                 <input type="text" value={name} onChange={handleInput}/>             </div>             <Child name={name} handleClick={handleChange}/>         </div>     ) }

      useCallback 作用

      // 用法 useCallback(()=>{   // to-do },[]) // 示例 function App(){   // 点击按钮调用此函数,但返回被缓存   const onClick = useCallback(() => {     console.log('我被缓存了,怎么点击都返回一样');   }, []);   return (      <button onClick={onClick}>点击</button>   ); }

      • useCallback接收 2 个参数,第一个为缓存的函数,第二个为依赖值
      • 主要用于缓存函数,第二次会返回同样的结果。

      useMemo 优化

      我们定义了一个total函数,内部使用 1 填充了100次,通过reduce计算总和,经过测试发现点击Increase按钮后,只会执行total1,不会执行total2,假设total计算量巨大,就会造成内存的浪费,通过useMemo可以帮我们缓存计算值。

      function Before(){     console.log('Demo1 Parent')     let [count,setCount] = useState(0)     const handleClick = ()=>{         setCount(count+1)     }     const total1 = ()=>{         console.log('计算求和1')         let arr = Array.from({ length:100 }).fill(1)         return arr.reduce((prev,next)=>prev+next,0)     }     // 缓存对象值     const total2 = useMemo(()=>{         console.log('计算求和2')         let arr = Array.from({ length:100 }).fill(1)         return arr.reduce((prev,next)=>prev+next,0)     },[count])     return (         <div>             <div className='l50'>                 <label>计数器:</label>                 <span className='mr10'>{count}</span>                 <button className='ml10' onClick={handleClick}>Increase</button>             </div>             <div>                 <label>总和:</label>                 <span>{total1()}</span>                 <span>{total2}</span>             </div>         </div>     ) }

      如何通过React Hook优化四种组件实现长尾关键词效果?

      useMemo 语法

      const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

      • 传入一个函数进去,会返回一个memoized值,需要注意的是,函数内必须有返回值
      • 第二个参数会依赖值,当依赖值更新时,会从新计算。

      useCallback 和 useMemo 区别

      他们都用于缓存,useCallback主要用于缓存函数,返回一个 缓存后 函数,而useMemo主要用于缓存值,返回一个缓存后的值。

      到此这篇关于React Hook 四种组件优化总结的文章就介绍到这了,更多相关React Hook 组件优化内容请搜索易盾网络以前的文章或继续浏览下面的相关文章希望大家以后多多支持易盾网络!