问题描述
我是ReactJS的新手,并对我如何更改在Map函数中实例化的特定组件的状态有疑问。 假设我有一个名为 panels 的简单组件,并且内部有N个 panel-item ,panel-item只是单个组件,在面板内部使用Map函数实例化了N次。像这样:
class Panels extends React.Component {
constructor(props) {
super();
this.state = {
panelItems: [
{ id: '1',text: 'A' },{ id: '2',text: 'B' },{ id: '3',text: 'C' },]
};
}
render() {
return (
<div>
{this.state.panelItems.map(item => (
<PanelItems key={item.id}>{item.text}</PanelItems>
))}
</div>
)
}
}
export default Panels;
现在我有一些问题:
- 假设我想要一个将面板项目1的状态(精确地为文本)更改为D的按钮,我该怎么做?
- 如果我回答了问题1,会否重新渲染整个面板组件(包括面板项目2和3)?
- 如果是,我如何只重新渲染组件面板项目1 为每个面板项目创建一个单独的组件?因为他们使用 相同的结构,只有里面的数据会改变。
谢谢。
解决方法
…更改面板项目1的状态(精确为文本)的按钮……
创建一个可以拼接更改的函数:
const updateText = (index,text) => {
// get the existing panel items from state.
// we don't want to mutate the original so we make a copy using spread syntax
const panelItems = [...this.state.panelItems];
panelItems.splice(
index,// starting at item "index"
1,// delete one item from the array
{ ...panelItems[index],text } // and insert its replacement
);
this.setState({ panelItems }); // set state with the new array
}
然后在按钮上单击onClick来调用该功能:
<button onClick={() => updateText(0,'the new text')}>Update Item 0</Button>
如果我回答了问题1,它会重新渲染整个面板组件吗?
作为一般规则,如果道具不变,React不会重新渲染纯组件。因此,我希望您的示例代码能够在不重新渲染每个PanelItem的情况下工作。
我如何只重新渲染组件面板项1,而不为每个面板项创建单独的组件
如果 看到不必要的重新渲染,则可以尝试让循环渲染仅包含道具的组件:
{this.state.panelItems.map(item => (
<Items key={item.id} item={item} />
))}
Item
组件已在其中:
const Item => ({item}) => <PanelItem>{item.text}</PanelItem>
只要道具prop是相同的对象,即使父状态发生变化,也不应重新渲染。