Javascript

React错题本---题1——使用useState更新状态失败

本文主要是介绍React错题本---题1——使用useState更新状态失败,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

听说每个好学生都会有个错题本,大概这就是我和大佬之差距吧...

但是!现在!为了接近大佬,我也决定开始记录错题了!虽然学了一年前端才开始写博客,虽然直到找工作才开始写博客。但是,我相信,只要肯开始,就一定不晚! emmmm.......应该,也许,可能不晚吧.... (虽然不知道能坚持多久,希望能坚持下去嗷)

好了,废话就到这,开始开始

关于使用useState更新状态失败的问题

在做自己的小项目的时候(做完的时候又可以发掘金水文章了,哇哈哈哈哈,我真是个天才),准备使用Hook来写项目。结果刚上手就遇到了这个问题。刚开始按照官方的写法更新点击次数的时候没有什么问题,一切似乎很正常。但到了自己写的时候,问题就出现了。

我在项目中使用了Ant Design中的表格,想做到点击删除事件,删除相应表格中的某一项,大概代码如下所示:

const [dataSource, setDataSource] = useState<Array<IDataSource>>([]);
const deleteUser = (id: string) => {
         let newData = dataSource;
         /*
         对!没错,删除数组中的数据的代码就是这么的朴实且真实,
         有更好的写法也请在评论区教教我
         */
        for (let i = 0; i < newData.length; i++) {
            const element = newData[i];
            if (element.id === id) {
                newData.splice(i, 1);
                break;
            }
        }
        console.log(newData)
        setDataSource(newData)
        console.log(dataSource)
    }
    
/*
    其余参数略,而且下面的代码我是放到了子组件中,
    让我一度怀疑是不是组件通信的问题,有点憨憨哦 :(
*/
 <Table  dataSource={dataSource} /> 
复制代码

结果发送了什么呢?结果就是打印的时候数据的确是变少了,删也删对了,但是数据就是没有更新,为啥?

就像我上面刚刚说的,我是把Table组件是放在了子组件中的,让我一度怀疑是不是我把组件通信用错了。但是又想到我子组件没有加判定条件,判断它是否渲染啊。讲道理父组件渲染了,子组件不设置阻止渲染是一定会渲染的呀。难道是针对我?

然后我企图加段代码来证明我的父组件是渲染了的

const [dataSource, setDataSource] = useState<Array<IDataSource>>([]);
const deleteUser = (id: string) => {
        for (let i = 0; i < newData.length; i++) {
            const element = newData[i];
            if (element.id === id) {
                newData.splice(i, 1);
                break;
            }
        }
        console.log(newData)
        setDataSource(newData)
        console.log(dataSource)
    }
 useEffect(()=> {
     console.log(dataSource)
 },[dataSource])
 <Table  dataSource={dataSource} /> 
复制代码

总所周知,在useEffect后面加上对应的变量就可以在变量变化时触发useEffect里的方法,哼哼,这下总该证明数据是变化了的吧。

但是,结果却狠狠打了我的脸......它没触发方法.....嘶.....不应该啊。数据的确是更新了的呀。头皮发麻。

然后,就在这个时候我突然想到了好像在哪里看到过,每次更新应该返回一个新的对象,然后我又仔细看了看我的删除操作,又觉得没问题啊let newData = dataSource,我这不是赋值给一个新对象了吗?

然后我突然发现了一件事情------我还真是个憨憨,哪有这样创建一个新对象的咯,这不是个把对象的指针给赋值过去了,是个鬼新对象哦。

再然后,我将代码改成了这样:

  const deleteUser = (id: string) => {
        for (let i = 0; i < dataSource.length; i++) {
            const element = dataSource[i];
            if (element.id === id) {
                dataSource.splice(i, 1);
                break;
            }
        }
        setDataSource([...dataSource])
    }
复制代码

这样总算是更新了,好了,就这样简单的一个问题花了我一个小时的时间,当然也有可能是昨天晚上写的有点晚了,状态不太好,对,一定是这样,不然我怎么可能犯这种低级错误嘛~

好了,我第一次写博客你居然能看完,对我来说你真的很不错哦,给看到这里的你点个赞

小小的总结一下

其实突然想到要返回一个新对象也是之前看redux时,天天听到要返回一个新对象,返回一个新对象,一直都不太理解为啥,没想到通过这次犯错居然想通了。其实还有一个类似的例子,在通过const声明一个对象时,可能我们会认为(起码我之前是这么认为的....)const声明的对象应该不能被更改

const a = {
    b: 1
}
a.b = 2
复制代码

按理说上面这个代码应该要报错啊,但是这样做确的确是可以的,b也的确是变成了2。

const a = {
    b : 1
}
a = {}
复制代码

但是你要是这样写那自然就报错了,其实const只是不让指向对象的那个指针发生更改。

在这里我理解成这样是JS没有做深层的对比,没有仔细的比较对象是否发生了更改,这样做的目的可能是为了节省性能开销吧(如果有准确答案建议在评论区教一下,thx)。

好了,第一篇博客到这里就结束了,虽然花了不少时间,但还是有点小充实,哇哈哈哈哈。

这篇关于React错题本---题1——使用useState更新状态失败的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!