更新树结构中的嵌套组件时遇到问题。我创建了以下示例来说明这个问题:Codesandbox.io
为完整起见,这是正在嵌套的组件:
class Node extends React.Component {
constructor(props) {
super(props);
this.state = {
selected: props.selected
};
this.toggleSelected = this.toggleSelected.bind(this);
}
toggleSelected() {
this.setState({
selected: !this.state.selected
});
}
render() {
return (
<>
<div onClick={this.toggleSelected}>
Selected: {this.state.selected ? "T" : "F"}, Depth: {this.props.depth}
</div>
{this.props.depth < 5 && (
<Node selected={this.state.selected} depth={this.props.depth + 1} />
)}
</>
);
}
}
树中的节点在单击时应该是可选择的,我还希望在所有子节点中(递归地)切换所选状态。我想我可以通过将this.state.selected
通过道具传递给孩子们来实现这一点,不幸的是,这似乎不起作用。
但是,子对象使用其旧状态重新呈现(可以理解,因为它们没有通过构造函数重新初始化)。正确的处理方法是什么?
我还尝试将键
属性传递给节点,以帮助区分元素,但没有成功。
编辑:以下是一些理想行为的示例:
考虑一下这棵树:
[ ] Foo
[ ] Foo A
[ ] Foo A1
[ ] Foo A2
[ ] Foo B
[ ] Foo B1
[ ] Foo B2
检查"Foo"时的预期结果-节点:
[x] Foo
[x] Foo A
[x] Foo A1
[x] Foo A2
[x] Foo B
[x] Foo B1
[x] Foo B2
检查“Foo A”-节点时的预期结果:
[ ] Foo
[x] Foo A
[x] Foo A1
[x] Foo A2
[ ] Foo B
[ ] Foo B1
[ ] Foo B2
如有任何方向正确的提示,我们将不胜感激。
免责声明:我将演示如何在React应用程序中呈现树并管理其状态,而不是修复OP问题中的代码。
创建无状态的节点
组件的数据驱动树并将状态管理留给根组件将更容易。
每个节点接收
selectedId
,并将其与自己的id
进行比较,以了解它们(及其子节点)是否应呈现为活动状态。
他们还会收到一个
setS选
回调,以通知父节点他们被点击了。
由于受来自父级的数据(它们的唯一ID、选定状态等)的驱动,它变得更通用,并留下大量空间来使用新特性扩充树。它也是解耦的,更容易测试,等等。
// Stateless node
const Node = ({ depth, setSelected, selected, id, nodes, selectedId }) => {
const isSelected = selected || selectedId === id;
return (
<React.Fragment>
{id && (
<div style={{ marginLeft: `${depth * 15}px` }}>
<input
type="checkbox"
onChange={() => setSelected(id)}
checked={isSelected}
/>
{id}
</div>
)}
{depth < 5 &&
nodes.map(nodeProps => (
<Node
key={nodeProps.id}
{...nodeProps}
selected={isSelected}
selectedId={selectedId}
setSelected={setSelected}
depth={depth + 1}
/>
))}
</React.Fragment>
);
};
Node.defaultProps = {
selected: false,
nodes: [],
depth: 0
};
// Parent keeps the selected Id
class App extends React.Component {
state = {
selected: null
};
setSelected = id => {
this.setState(({ selected }) => ({
selected: selected !== id ? id : null
}));
};
render() {
return (
<div className="App">
<Node
nodes={this.props.tree}
selectedId={this.state.selected}
setSelected={this.setSelected}
/>
</div>
);
}
}
const treeData = [
{
id: "Foo",
nodes: [
{
id: "Foo A",
nodes: [{ id: "Foo A1" }, { id: "Foo A2" }]
},
{
id: "Foo B",
nodes: [{ id: "Foo B1" }, { id: "Foo B2" }]
}
]
}
];
ReactDOM.render(
<App tree={treeData} />,
document.getElementById("root")
);
input {
cursor: pointer;
}
html prettyprint-override"><script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="root"></div>
你应该像这样使用getDerivedStateFromProps:
constructor(props) {
super(props);
this.state = {
selected: props.selected,
propsSelected: props.selected
};
this.toggleSelected = this.toggleSelected.bind(this);
}
static getDerivedStateFromProps(props, state) {
if (props.selected !== state.propsSelected)
return {
selected: props.selected,
propsSelected: props.selected
};
}
我们总是将prevProp存储在状态中。每当我们遇到存储在状态中的道具和来自父级的道具发生变化时,我们都会更新从父级和组件本身控制的状态部分(selected
),并且我们也会将道具保存在该状态,以备将来扩散。
通常,可以从父级和自身控制的组件将涉及此类逻辑。大多数react组件库中的输入组件就是一个理想的例子。
我正在尝试学习React(使用redux),所以我正在制作一个应用程序,在其中我可以创建训练计划,将训练添加到计划中,然后将训练添加到训练中。 PlanListComponent 我的PlansList组件为每个计划呈现一张卡片。在这张卡片中,它为该计划中的每个训练呈现一个训练列表。将训练添加到计划后,“计划列表”组件不会重新渲染。添加的训练仅在我刷新页面后显示。我之所以选择这种情况,是因为我必须
问题内容: 所以,我有多个ReactComponent。最初,我以为会有一个带有其自身状态的父组件(简称为GrandPa),它将有关其状态的一些信息传递给另一个组件(称为Parent)。同样,父母将他的一些财产传给孩子,孩子则传给孙子。因此,我们具有层次结构: 爷爷->父母->孩子->孙子 但是,我很快意识到,当我使用method 更改GrandPa的状态时,所做的更改不会沿通道向下级联。我意识到
我正在尝试更新嵌套数组中的值,但无法使其工作。 我的对象是这样的 提前谢谢!
问题内容: 添加评论时,我试图使angular.js视图本身进行更新。我的代码如下: 范围在输入时更新: 调试$ scope.currentItem显示注释已添加到其中,但是视图未显示新注释。我怀疑$ scope仅在其第一级被监视,这就是为什么视图不更新的原因。是这样吗?如果可以,我该如何解决? 解决方案:正如Ajay在下面的回答中所建议的那样,我将数组推入包装为apply函数,如下所示: 问题答
我正在使用平均堆栈在网格中显示以下数组。 嵌套数组:
问题内容: 我正在尝试更新嵌套数组中的值,但无法使其正常工作。 我的对象是这样的 我需要将值推送到“ answeredBy”数组。 在下面的示例中,我尝试将“成功”字符串推到“ 123 _id”对象的“ answeredBy”数组中,但是它不起作用。 我找到了此链接,但其答案仅表示我应该使用类似结构的对象而不是数组。这不适用于我的情况。我真的需要将我的对象嵌套在数组中 如果您能在这里帮助我,那就太