听说每个好学生都会有个错题本,大概这就是我和大佬之差距吧...
但是!现在!为了接近大佬,我也决定开始记录错题了!虽然学了一年前端才开始写博客,虽然直到找工作才开始写博客。但是,我相信,只要肯开始,就一定不晚! emmmm.......应该,也许,可能不晚吧.... (虽然不知道能坚持多久,希望能坚持下去嗷)好了,废话就到这,开始开始
在做自己的小项目的时候(做完的时候又可以发掘金水文章了,哇哈哈哈哈,我真是个天才),准备使用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)。
好了,第一篇博客到这里就结束了,虽然花了不少时间,但还是有点小充实,哇哈哈哈哈。