我不确定是否最好在单个子组件或父组件中保留状态。
我有一个父组件,它将容纳一个需要能够按需复制的子组件。
我有几个问题:
我在哪里存储单个组件的状态是在组件本身还是在父组件中?
如果它在子组件中,我如何告诉父组件更新其他子组件。
如果它在父级中,如何将函数传递给子级以更新 ITS 状态而不是父级状态?
如何访问每个组件状态并告诉它根据另一个子状态的变化进行更改?
目前,我正在将一个新的“卡”组件推送到一个数组中,该数组跟踪我需要在“板”上渲染的所有组件。
我无法概念化管理一切状态以及如何访问每个子项的最佳方法。他们有个人身份证吗?我怎样才能改变他们所有的状态。
- -------------------- 董事会 -------------------------- *里>
import React from "react";
import Card from "./Card";
export default class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
cards: [<Card />]
};
}
componentDidMount() {}
createCard() {
this.state.cards.push(<Card />);
this.forceUpdate();
}
render() {
return (
<div id="Board">
<button onClick={() => this.createCard()}>Create Card</button>
{this.state.cards.map(card => (
<Card />
))}
</div>
);
}
}
- -------------------------- 卡 -------------------- ---------- *
export default class Card extends React.Component {
constructor(props) {
super(props);
this.state = {
active: false
};
}
cardClick = () => {
this.setState({
active: !this.state.active
});
};
render(cardClick) {
return (
<div>
{this.state.active ? (
<div
className="activeCard"
id="card"
onClick={() => this.cardClick()}
>
Active
</div>
) : (
<div
className="inactiveCard"
id="card"
onClick={() => this.cardClick()}
>
Inactive
</div>
)}
</div>
);
}
} ```
最佳答案
好吧,让我们从头开始。我想您有一些想要呈现为 <Card />
的数据,每个数据项一个。您保存的不是状态中的组件,而是数据。例如:
this.state = {
data: [
{value: 'Cat 1'},
{value: 'Cat 2'},
{value: 'Cat 3'}
]
}
在这种情况下,父级保存数据是正确的。然而,lifting the state up (React docs link)的整个概念并不是那么难。大多数情况下,这是一个问题:是否有多个组件关心/依赖于同一状态?如果答案是肯定的,通常 parent 应该持有它。让每张卡保持其自己的事件状态是正确的。然而, parent 也可以这样做。那么我们就这样做吧:
Board.js
import React from 'react';
import {Card} from './Card';
class Board extends React.Component{
state = {
data: [
{value: 'Cat 1'},
{value: 'Cat 2'},
{value: 'Cat 3'}
],
activeCard: null,
}
cardClick = id => {
this.setState({ activeCard: id })
}
addCard = () => {
const newCard = { value: 'Some val here' };
this.setState({ data: [...this.state.data, newCard] });
}
render(){
return(
<div id="Board">
<button onClick={this.addCard}>Add a card</button>
{this.state.data.map((item, index) =>
<Card key={index}
value={item.value}
active={this.state.activeCard === index}
cardClick={this.cardClick}
index={index}
/>
)}
</div>
)
}
}
export default Board;
通过这样做,我们的 parent 可以管理一切。并不是说这是唯一正确的方法,但这让我们拥有 Card
组件作为“哑”功能组件。请小心 - 这种特定方法依赖于永不改变顺序的数据,因为它依赖于 .map
索引,从 0 到数据长度 - 1。
Card.js
import React from 'react';
const Card = props => (
<div
className={props.active ? 'activeCard' : 'inactiveCard'}
onClick={() => props.cardClick(props.index)}
>
Active
</div>
);
export { Card };
您发布的内容和我所做的内容之间存在一些关键差异。
1) 您正在使用相同的 id="card"
映射卡片。这很糟糕,id 应该是唯一的。另外,除非您确实需要它,否则可以省略它。
2) 我正在切换 className
基于事件卡的索引。如果当前卡(假设为 2)也是事件卡,则它将具有 activeCard
类(class)名称。
3) 最后,我将一个函数传递给子级来更新父级状态。通过这样做,我将状态包含在父级中,并且每次更新它时,它也会反射(reflect)在子级中。这并不是说您为卡片使用基于类的组件的方法是错误的,但我认为这更简单。
4)只是把它扔在那里,WAI-ARIA不太同意 div 有 onClick
事件。为了使互联网成为一个很酷、易于访问的地方,您可以将 role="button"
在 div 上,表示它是一个按钮。这还要求它是可聚焦的,以及键盘事件监听器,在这种情况下,您最好只使用 <button>
元素是否可点击。
回答您的其他问题:
父级自动将所有状态更改传播给所有关心它的子级
所有子组件都独立于父组件,例如,如果它们有自己的状态,则父组件不关心。只有当它们共享状态和状态更新函数时,这才变得相关,因此只有当您专门将此类函数传递给子级时
如果 children 共享一个状态,那么它应该被提升,这在链接的文档中有解释!
编辑:对于给定的示例,我假设您一次只需要一张事件卡。如果情况并非如此,要么让每张卡保持其事件状态,就像基诺·克莱顿建议的那样,要么更改 activeCard
放入数组中,根据事件卡数组检查每张卡的索引
关于javascript - 操作多个子组件的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54395209/