<
>

关于react中列表渲染的局部刷新问题

2022-08-04 15:12:42 来源:易采站长站 作者:

目录react中列表渲染的局部刷新react实现实时/局部刷新初始做法示例增加数据修改数据删除数据react中列表渲染的局部刷新最近在写demo的时候遇到一个更新列表中某个的对象的某个值,最期待的结果...

目录
react中列表渲染的局部刷新
react实现实时/局部刷新
初始做法示例
增加数据
修改数据
删除数据

react中列表渲染的局部刷新

最近在写demo的时候遇到一个更新列表中某个的对象的某个值,最期待的结果肯定是局部刷新,但是我们往往在改变值之后会遇到全局都刷新的问题,以下为个人实验出来的一个小技巧。

首先我有以下数据需要通过react的列表方法渲染:

let list=[
  {
    id:1,
    show:false
  },
  {
    id:2,
    show:false
  },
  {
    id:3,
    show:false
  }
]

我们通过以下react方法进行渲染:

render(){
  return (
    {list.map((val)=>{
      <DemoComponent val={val}/>
    })}
  )
}

在这里我们需要重新写一个DemoComponent的组件:

import React,{Component} from 'react';
export class DemoComponent extends Component{
  render(){
    <div>
     <div>this.props.val.id</div>
     <button onClick={()=>this.toggleDialog()}>toggle</button> 
    </div>
  }
  toggleDialog(){
    // 更改val.showDialog相关操作。
  }
  shouldComponentUpdate(nextProps){
    return jsON.stringify(nextProps) !== JSON.stringify(this.props);
  }
}

当我们点击第一个button,这个时候就能达到局部刷新,只刷新第一个DemoComponent组件的效果了。

但以上操作是什么原理呢?

首先,大家平时都推荐使用的PureComponent不能在这里使用,因为这个组件没有shouldComponentUpdate这个钩子函数,虽然PureComponent也有对比props和nextProps并自行判断当前组件是否需要重新渲染的功能,但是这个对比对对象是没有用的,因为{} === {}是返回false的(对这个知识点不理解的朋友可以去看看堆栈相关的知识),数组同理。

那么为了让其他列表组件没有必要多去render一次,所以我在shouldComponentUpdate中取了个巧,直接JSON.stringify,将两个对象转换成字符串进行比较,这样就方便的多。

当然这里也是自己为了不去写一个isEqual方法而偷懒的做法,这样做的好处是简单方便,也节省时间(isEqu编程al方法必然会for-in循环,对于更复杂的情况甚至需要递归,在内存消耗和时间复杂度上肯定会比JSON.stringify严重),缺点在于可拓展性不高,如果是个数组,就比较头疼。 

react实现实时/局部刷新

在React项目中,经常会遇到诸如:删除某一行的同时同时刷新表格展示最新的表格,而不是删除后,手动刷新。

原先是在删除时再次调用生命周期函数中展示表格列表的函数,但会影响性能。

总结:通过JS数组修改usestate中的状态。

初始做法示例

useEffect(() => {
    httpOffer()
  }, [])
//获取列表
  const httpOffer = () => {
    offerList()
      .then(res => {
        // console.log('offer', res)
        if (res.status === 200) {
          if (res.data.code === 0) {
            const data = res.data.data
            data.length > 0 && data.forEach(el => {
              el.key = el.id
            });
            setOffers(data)
          } else {
            message.error(res.data.msg)
          }
        } else {
          message.info('network failed')
        }
        setLoading(false)
      })
      .catch(err => {
        setLoading(false)
        throw err
      })
  }
const showModalDel = (id) => {
    delOffer({ id })
      .then(res => {
        if (res.status === 200) {
          if (res.data.code === 0) {
            //之前的做法,刷新页面
            httpOffer()
            message.info(res.data.msg)
          } else {
            message.error(res.data.msg)
          }
        } else {
          message.error('Network failed!')
        }
      })
      .catch(err => {
        throw err
      })
  }

目前可以使用JS数组和usestate进行同样的操作。

增加数据

addOffer(params)
        .then(res => {
          if (res.status === 200) {
            if (res.data.code === 0) {
              let data = res.data.data
              //重点
              setOffers([...offers, { key: data.id, id: data.id, ...params}])
             
              message.info(res.data.msg)
              setVisible(false)
            } else {
              message.error(res.data.msg)
            }
          } else {
            message.error('Network failed!')
          }
        })
        .catch(err => {
          console.log(err)
        })

修改数据

editOffer(params)
        .then(res => {
           //重点
              setOffers(offers.map(item => {
                if(item.id === params.id){
                  item.id = params.id,
                  item.adv_id = params.adv_id,
                }
                return item
              }))
              setVisible(false)
        })
        .catch(err => {
          console.log(err)
        })

删除数据

const showModalDel = (id) => {
    delOffer({ id })
      .then(res => {
        //重点
        setOffers(offers.filter(item => item.id != id ))
        message.info(res.data.msg)
      })
      .catch(err => {
        throw err
      })
  }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。 

暂时禁止评论

微信扫一扫

易采站长站微信账号