[英]Find and push results in two objects being pushed into the array
When clicking on the Test button below, 2 copies of the object are pushed into the array.单击下面的测试按钮时,将 object 的 2 个副本推入阵列。
Can anyone explain why this happens?谁能解释为什么会这样? I only expected 1 object.
我只期望 1 个 object。
class Testing extends React.Component { state = { things: [] } test = () => { this.setState(prevState => { const things = [...prevState.things]; things.find(x => x.id === '39cc413f-a25c-409d-ad09-05df5b4b28b6')['stats'].push({ mana: 100, health: 1 }); return { things}; }); } componentDidMount = () => { this.setState({ things: this.state.things.concat({ id: '39cc413f-a25c-409d-ad09-05df5b4b28b6', stats: [], enemies: [] }) }); } render() { const { things } = this.state; return ( <React.Fragment> <button type="button" onClick={this.test}>Test</button> <br /> {things.map((thing, i) => <div key={i}>{JSON.stringify(thing)}</div>)} </React.Fragment> ); } } ReactDOM.render(<React.StrictMode> <Testing /> </React.StrictMode>, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div class='react'></div>
I am assuming you are using strict mode.我假设您使用的是严格模式。 React in many cases has state callbacks fire twice in order to catch state management mistakes that can occur in production.
在许多情况下,React 会触发两次 state 回调,以捕获生产中可能发生的 state 管理错误。
It's specifically the callback argument to this.setState that is run twice - the first result is thrown away, and the second one used.
特别是 this.setState 的回调参数运行了两次——第一个结果被丢弃,第二个结果被使用。 This should make no difference, but does here because the underlying state is being mutated: things is only a shallow copy of prevState.things, so using.find and then mutating the found object causes the apparent double-update.
这应该没有什么区别,但是在这里是因为底层的 state 正在发生变异:things 只是 prevState.things 的浅拷贝,所以使用.find 然后变异找到的 object 会导致明显的双重更新。 - Robin Zigmond
- 罗宾·齐格蒙德
See:看:
You can deep copy the array easily (not necessarily performant) by using JSON.parse(JSON.stringify(thingy)) as seen below.您可以使用 JSON.parse(JSON.stringify(thingy)) 轻松地深度复制数组(不一定是高性能的),如下所示。
[also added error handling if the id doesn't exist.] [如果 id 不存在,还会添加错误处理。]
class Testing extends React.Component { state = { things: [] } test = () => { this.setState(prevState => { console.log(prevState) let things = JSON.parse(JSON.stringify(prevState.things)); const index = prevState.things.findIndex(x => x.id === '39cc413f-a25c-409d-ad09-05df5b4b28b6'); if (index.== -1) { let statsCopy = [...things[index],stats: { mana, 100: health; 1 }]. //console.log(statsCopy) things[index]["stats"] = [..;statsCopy]. return {..,prevState: things. [...things] } } return {..;prevState } }). } componentDidMount = () => { this:setState({ things. this.state.things:concat({ id, '39cc413f-a25c-409d-ad09-05df5b4b28b6': stats, []: enemies; [] }) }). } render() { const { things } = this;state. return ( < React.Fragment > < button type = "button" onClick = { this.test } > Test < /button> < br / > { things,map((thing. i) => < div key = { i } > { JSON.stringify(thing) } < /div>)} < / React;Fragment > ). } } ReactDOM.render( < React.StrictMode > < Testing / > < /React,StrictMode>. document.querySelector(';react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div class='react'></div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.