【发布时间】:2021-01-14 08:49:17
【问题描述】:
我是 React 的新手,所以我很感激任何关于如何使它更符合习惯的建议。 这是一个玩具示例,但在实际示例中,我的状态包含一个实体数组。对此实体数组的任何更改都应触发重新渲染。任何用户输入或其他逻辑都可能导致一次添加或删除多个实体。
我目前通过复制实体列表、附加新项目和设置状态来将实体添加到状态。这也会触发重新渲染,这正是我想要的:
let nextEntities = Object.assign([], this.state.entities) as boolean[];
nextEntities.push(val);
this.setState({
entities: nextEntities
});
但是,如果我连续多次执行此操作,则只会添加最后一个实体,因为 this.state.entities 不是最新的。
我什至尝试创建要添加的实体队列,并从setState 的回调中触发额外的setState 调用,但这达到了堆栈帧限制。
我知道我可以在setTimeout 回调中隔开多个添加,但这似乎很愚蠢。
钩子的一些用法是答案吗?
这是我的最小示例:https://codesandbox.io/s/headless-darkness-w1wt1?file=/src/index.tsx:0-1375
import React from "react";
import ReactDOM from "react-dom";
//My React component state has an array of entities in it
interface State {
entities: boolean[];
}
interface Props {}
export class App extends React.Component<Props, State> {
constructor(props) {
super(props);
this.state = {
entities: [true, false]
};
}
onClick = () => {
console.log("onclick! current state:", this.state.entities);
//based on user input,
// multiple items may get added to the array per frame
this.addToStateList(true);
this.addToStateList(false);
};
addToStateList(val: boolean) {
let nextEntities = Object.assign([], this.state.entities) as boolean[];
//TODO: in a non-toy example, we'd do some extra side-effects on each add here.
nextEntities.push(val);
this.setState({
entities: nextEntities
});
console.log("just tried to push new value:", val);
}
render() {
let lItems = this.state.entities.map((val: boolean, index: number) => (
<div style={{ display: "inline" }} key={index}>
{(val ? "true" : "false") + ", "}
</div>
));
return (
<div onClick={this.onClick}>click to test. Current value: {lItems}</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
我确定您要提供的一个潜在建议是批量添加要添加的实体,以便它们都在一个 setState 调用中添加。在我的真实案例中,这很尴尬,因为:
- 实体在代码中的不同位置添加或删除,因此将它们批处理在一起并不容易
- 在添加时,我需要将要添加的实体与所有预先存在的实体(如碰撞检测)进行比较。比较(要添加的实体)与(状态中的预先存在的实体 + 要添加的其他实体,除了当前正在添加的实体)只是比较麻烦。
【问题讨论】:
标签: reactjs typescript react-hooks state