zoukankan      html  css  js  c++  java
  • 使用usecallback/useMemo+usereducer解决单独使用usereducer出现的重复渲染问题

    react中,单独使用usereducer的hooks进行开发的话会出现重复渲染的情况,代码如下:

     // const setHotelList= 
      const [hotelList,dispatchHotelList]=useReducer((state: any[],action: any)=>{
        switch(action.type){
          //会发现这样的地方不走usecallback会输出两次
          case 'add':
            console.log([...state,action.payload])
            return [...state,action.payload]
           case 'modify':
             return state.map(item=>{
               return item.id===action.payload.id?{...item,checked:action.payload.checked}:item
             })
       default:
            return state
        }
      },[])
      const addArr=()=>{
        let id= Math.floor(Math.random()*100+1);
        var Arr = ["王","李","张","赵","陈","刘"];
        var nameArr=['香蕉','苹果','柚子','橘子','菠萝']
      //这里是随机获取数组元素的写法
    var idx = Math.floor(Math.random() * Arr.length + 1)-1; var nameIdx = Math.floor(Math.random() * nameArr.length + 1)-1; dispatchHotelList({payload:{name:`${Arr[idx]}${nameArr[nameIdx]}`,id,checked:false},type:'add'}) } const selItem=(item:any)=>{ dispatchHotelList({payload:item,type:'modify'}) } return ( <> <ul> { hotelList.map((item: any,index)=>{ return <li key={index} style={{backgroundColor:`${item.checked?'green':'red'}`}} onClick={()=>{selItem(item)}}>{item.name}</li> }) } </ul> <button onClick={addArr}>添加</button> </> );

    对于出现的问题,可以通过usecallback进行解决,这个钩子只有在依赖项变更后才会重新进行渲染,官网解释如下:

    把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。

    所以改造后可以这么写:

    const setHotelList= useCallback((state: any[],action: any)=>{
        switch(action.type){
          //会发现这样的地方不走usecallback会输出两次
          case 'add':
            console.log([...state,action.payload])
            return [...state,action.payload]
    
           case 'modify':
             return state.map(item=>{
               return item.id===action.payload.id?{...item,checked:action.payload.checked}:item
             })
    default:
            return state
        }
      },[])
      // const setHotelList= 
      const [hotelList,dispatchHotelList]=useReducer(setHotelList,[])
      const addArr=()=>{
        let id= Math.floor(Math.random()*100+1);
        var Arr = ["王","李","张","赵","陈","刘"];
        var nameArr=['香蕉','苹果','柚子','橘子','菠萝']
        var idx = Math.floor(Math.random() * Arr.length + 1)-1;
        var nameIdx = Math.floor(Math.random() * nameArr.length + 1)-1;
        dispatchHotelList({payload:{name:`${Arr[idx]}${nameArr[nameIdx]}`,id,checked:false},type:'add'})
      }
    
      const selItem=(item:any)=>{
        dispatchHotelList({payload:item,type:'modify'})
      }

    使用useMemo可以如下写法:

      const setHotelList= useMemo(()=>{
        return (state: any[],action: any)=>{
          switch(action.type){
            //会发现这样的地方不走usecallback会输出两次
            case 'add':
              console.log([...state,action.payload])
              return [...state,action.payload]
            case 'modify':
              return state.map(item=>{
                return item.id===action.payload.id?{...item,checked:action.payload.checked}:item
              })
            default:
              return state
          }
        }
      },[])

    这里useMemo和useCallBack区别在于。useMemo缓存的是函数的结果,而useCallBack缓存的是整个函数

    问题解决

  • 相关阅读:
    c#驱动操作mongodb辅助类MongoDBHelper
    c#多线程lock无效
    利用Aspose.Words将html转成pdf和将html转成word
    前后端值映射的问题
    本机部署流程详解
    Git 安装配置手册
    js对象数组(JSON) 根据某个共同字段 分组
    jquery中的$.fn的用法
    JSON.parse()与JSON.stringify()的区别
    添加编辑 时 数据不可重复验证
  • 原文地址:https://www.cnblogs.com/llcdbk/p/13802573.html
Copyright © 2011-2022 走看看