当一个改变时如何更新每个映射组件中的组件状态
Posted
技术标签:
【中文标题】当一个改变时如何更新每个映射组件中的组件状态【英文标题】:How to Update Component State in Each of Mapped Components When One Changes 【发布时间】:2021-04-22 08:00:23 【问题描述】:我正在制作一个将图像呈现到屏幕上的基本应用程序。目标是不要多次单击同一图像。我在 App comp 中使用父状态来计算分数(第一次点击次数)和 Image 组件中的本地组件状态,以查看是否已经点击了图像。 App 组件是这样的:
class App extends React.Component
state = score: 0 ;
array = [1, 2, 3]
handleScoreIncrement = (e) =>
this.setState( score: this.state.score + 1 )
console.log(this.state.score)
handleRestart = () =>
this.setState( score: 0 )
render()
return (
<div>
<Header
score=this.state.score />
this.array.map((cv, i, arr) =>
return (
<div key=cv>
<Image
score=this.state.score
increaseScore=this.handleScoreIncrement
restart=this.handleRestart
/>
</div>
)
)
</div>
)
;
export default App;
我将 App 组件中的回调作为道具传递给图像组件以更改状态,如下所示。就留在我身边吧。 图片组件:
class Image extends React.Component
state =
clickedAlready: false,
score: this.props.score
handleRestart = () =>
this.props.restart();
if (this.props.score === 0)
this.setState( clickedAlready: false )
handleClickEvent = (e) =>
if (this.state.clickedAlready)
alert('Clicked Already')
this.handleRestart()
this.setState( clickedAlready: false )
else
this.props.increaseScore();
this.setState( clickedAlready: true )
console.log(this.state.score)
render()
return (
<div
style= border: '1px solid red', marginTop: 5
onClick=this.handleClickEvent>Image Would Go Here
</div>
)
export default Image;
现在解决问题:我遇到的问题是,每次单击图像时,它都会正确递增,但是一旦我按了两次相同的图像,重置游戏并重新开始,只有特定的图像会改变它状态回到 clickedAlready: false (以便重新开始游戏),而其余的仍然说他们已被点击。如果在重置时,除了双击的组件之外的所有组件都保持其先前的状态,我将无法重新启动游戏。 我希望我的 Image 组件中的事件处理程序会重置 Image comp 和 App 组件的状态,从而重新渲染这两个组件,但也许我遗漏了一些东西。请帮忙
本质上,我希望在双击一个 Image 组件时,让所有 Image 组件将其状态重新设置为 clickedAlready: false。
【问题讨论】:
子Image
组件不会对传递的 score
属性的更新做出反应。此外,将 score
属性复制到本地状态是 React 中的反模式,您需要单一的事实来源。由于孩子们已经在使用回调来更新父母的状态,所以他们应该只响应对该状态的更新。有空我看看能不能做个演示。
我明白你的意思——在图像组件中。我的意思是删除这种冗余,因为代码可以在 Image 组件中没有 score 道具的情况下正常工作。只是希望能够重置具有 clickedAlready: true 状态的图像组合的所有“双”图像状态(可以这么说)。
【参考方案1】:
主要更新内容:
图片
当score
属性值更新为0
时,使用componentDidUpdate
重置clickedAlready
状态。这允许所有Image
组件在父组件中重置score
状态时“重置”。
componentDidUpdate(prevProps)
if (prevProps.score !== this.props.score && this.props.score === 0)
this.setState( clickedAlready: false );
更新handleClickEvent
以检查clickedAlready
状态以回调以重置游戏或提高分数并更新点击状态。
handleClickEvent = (e) =>
const clickedAlready = this.state;
const increaseScore, restart = this.props;
if (clickedAlready)
alert("Clicked Already");
restart();
else
increaseScore();
this.setState( clickedAlready: true );
;
沙盒演示中的完整代码
const Header = ( score ) => <h1>Score: score</h1>;
class Image extends React.Component
state =
clickedAlready: false
;
componentDidUpdate(prevProps)
if (prevProps.score !== this.props.score && this.props.score === 0)
this.setState( clickedAlready: false );
handleClickEvent = (e) =>
const clickedAlready = this.state;
const increaseScore, restart = this.props;
if (clickedAlready)
alert("Clicked Already");
restart();
else
increaseScore();
this.setState( clickedAlready: true );
;
render()
const clickedAlready = this.state;
return (
<div
style= border: "1px solid red", marginTop: 5
onClick=this.handleClickEvent
>
Image Would Go Here clickedAlready && " - clicked"
</div>
);
class App extends React.Component
state = score: 0 ;
array = [1, 2, 3];
componentDidUpdate()
const score = this.state;
console.log(score);
if (score === this.array.length)
alert("Won");
this.handleRestart();
handleScoreIncrement = (e) =>
this.setState( score: this.state.score + 1 );
;
handleRestart = () =>
this.setState( score: 0 );
;
render()
return (
<div>
<Header score=this.state.score />
this.array.map((cv, i, arr) =>
return (
<div key=cv>
<Image
score=this.state.score
increaseScore=this.handleScoreIncrement
restart=this.handleRestart
/>
</div>
);
)
</div>
);
export default App;
【讨论】:
以上是关于当一个改变时如何更新每个映射组件中的组件状态的主要内容,如果未能解决你的问题,请参考以下文章