Javascript 在返回之前设置状态总是失败,因为返回尚未完成
我发现了许多类似的问题,但我永远无法找到解决方案,我不知道如何解决我的问题 我有一个相当大的网格(2D数组)正在生成,我在其中映射它并插入一个节点组件。此过程在网格组件生成此网格时在网格组件内完成 分解我的bug: 我以前在ComponentDidMount中有过它,它会计算数组的宽度和高度并创建网格,这在创建网格时起到了作用,不过,最佳实践告诉我,除非是HTTP调用数据,否则不会在ComponentDidMount中设置状态 在Javascript 在返回之前设置状态总是失败,因为返回尚未完成,javascript,reactjs,Javascript,Reactjs,我发现了许多类似的问题,但我永远无法找到解决方案,我不知道如何解决我的问题 我有一个相当大的网格(2D数组)正在生成,我在其中映射它并插入一个节点组件。此过程在网格组件生成此网格时在网格组件内完成 分解我的bug: 我以前在ComponentDidMount中有过它,它会计算数组的宽度和高度并创建网格,这在创建网格时起到了作用,不过,最佳实践告诉我,除非是HTTP调用数据,否则不会在ComponentDidMount中设置状态 在render(){return()}中,我有一个if语句,它检查状
render(){return()}
中,我有一个if语句,它检查状态是否未定义,并呈现某种消息,例如初始化网格
,如果数组的状态未定义,它将呈现DisplayGrid()
。即使在渲染栅格之后,if也不会触发
这里的底线是,我不知道如何在加载状态之前正确延迟渲染,或者在设置状态后重新加载渲染
我尝试在GenerateGrid()
中使用回调来调用DisplayGrid()
,并让我的主要组件返回调用GenerateGrid()
,但是调用DisplayGrid后,结果是一个无休止的循环,或者再次调整后,一个未定义的映射被调用
以下是完整组件的一个损坏示例:
export default class Grid extends React.Component {
constructor(){
super();
this.state = {
nodeSize : 50,
nodeArray : [],
}
}
// Generate a dynamic grid
GenerateGrid = () => {
const newNodeArray = [];
const nodeSize = this.state.nodeSize;
// get window inner hieght + width based on browser size (onstart) and remove 50px from height due to header
let screenWidth = window.innerWidth;
let screenHieght = window.innerHeight - 50;
// get max amount of nodes based on node size
const whNodes = [Math.trunc(screenWidth / nodeSize),Math.trunc(screenHieght / nodeSize)];
// begin creating the 2D array representing the grid
for (let row = 0; row < whNodes[0]; row++) {
const newRow = []; // initialize 1D array
for (let col = 0; col < whNodes[1]; col++) {
newRow.push([]); // initalize 2D array
}
newNodeArray.push(newRow); // push into newNodeArray
}
this.setState(
{nodeArray : newNodeArray}, // set nodeArray state with the new 2D array based on viewport.
// this.DisplayNodes() // call function once completed if I used this GenerateGrid method within the return render (does not work)
);
}
DisplayNodes = () => {
const {nodeArray} = this.state.nodeArray; // get the node array from state
console.log(nodeArray); // the bug is here. Always undefined.
return (
<div id="grid">
{nodeArray.map((row, rowIdx) => {
return (
<div>
{row.map((node,nodeIdx) => <Node/>)}
</div>
)
})}
</div>
)
}
render() {
const {nodeArray} = this.state.nodeArray; // get the node array from state
console.log(nodeArray);
return (
<div id="grid-wrapper">
{this.GenerateGrid()}
</div>
)
}
}
render() {
return (
<div id="grid-wrapper">
{this.GenerateGrid()} //create a infinte setState loop
</div>
)
}
然后在主组件的渲染中:
export default class Grid extends React.Component {
constructor(){
super();
this.state = {
nodeSize : 50,
nodeArray : [],
}
}
// Generate a dynamic grid
GenerateGrid = () => {
const newNodeArray = [];
const nodeSize = this.state.nodeSize;
// get window inner hieght + width based on browser size (onstart) and remove 50px from height due to header
let screenWidth = window.innerWidth;
let screenHieght = window.innerHeight - 50;
// get max amount of nodes based on node size
const whNodes = [Math.trunc(screenWidth / nodeSize),Math.trunc(screenHieght / nodeSize)];
// begin creating the 2D array representing the grid
for (let row = 0; row < whNodes[0]; row++) {
const newRow = []; // initialize 1D array
for (let col = 0; col < whNodes[1]; col++) {
newRow.push([]); // initalize 2D array
}
newNodeArray.push(newRow); // push into newNodeArray
}
this.setState(
{nodeArray : newNodeArray}, // set nodeArray state with the new 2D array based on viewport.
// this.DisplayNodes() // call function once completed if I used this GenerateGrid method within the return render (does not work)
);
}
DisplayNodes = () => {
const {nodeArray} = this.state.nodeArray; // get the node array from state
console.log(nodeArray); // the bug is here. Always undefined.
return (
<div id="grid">
{nodeArray.map((row, rowIdx) => {
return (
<div>
{row.map((node,nodeIdx) => <Node/>)}
</div>
)
})}
</div>
)
}
render() {
const {nodeArray} = this.state.nodeArray; // get the node array from state
console.log(nodeArray);
return (
<div id="grid-wrapper">
{this.GenerateGrid()}
</div>
)
}
}
render() {
return (
<div id="grid-wrapper">
{this.GenerateGrid()} //create a infinte setState loop
</div>
)
}
render(){
返回(
{this.GenerateGrid()}//创建一个infinte setState循环
)
}
这也会抛出一个错误,即映射未定义(即在调用
DisplayGrid
方法之前未设置状态)。您可能不应该在render
函数中调用setState
。
您可以尝试从GenerateGrid
返回newnoderray
,并将其传递给DisplayNodes
:
GenerateGrid = () => {
const newNodeArray = [];
const nodeSize = this.state.nodeSize;
// get window inner hieght + width based on browser size (onstart) and remove 50px from height due to header
let screenWidth = window.innerWidth;
let screenHieght = window.innerHeight - 50;
// get max amount of nodes based on node size
const whNodes = [
Math.trunc(screenWidth / nodeSize),
Math.trunc(screenHieght / nodeSize)
];
// begin creating the 2D array representing the grid
for (let row = 0; row < whNodes[0]; row++) {
const newRow = []; // initialize 1D array
for (let col = 0; col < whNodes[1]; col++) {
newRow.push([]); // initalize 2D array
}
newNodeArray.push(newRow); // push into newNodeArray
}
return this.DisplayNodes(newNodeArray);
};
您可能不应该在
render
函数中调用setState
。
您可以尝试从GenerateGrid
返回newnoderray
,并将其传递给DisplayNodes
:
GenerateGrid = () => {
const newNodeArray = [];
const nodeSize = this.state.nodeSize;
// get window inner hieght + width based on browser size (onstart) and remove 50px from height due to header
let screenWidth = window.innerWidth;
let screenHieght = window.innerHeight - 50;
// get max amount of nodes based on node size
const whNodes = [
Math.trunc(screenWidth / nodeSize),
Math.trunc(screenHieght / nodeSize)
];
// begin creating the 2D array representing the grid
for (let row = 0; row < whNodes[0]; row++) {
const newRow = []; // initialize 1D array
for (let col = 0; col < whNodes[1]; col++) {
newRow.push([]); // initalize 2D array
}
newNodeArray.push(newRow); // push into newNodeArray
}
return this.DisplayNodes(newNodeArray);
};
没有错误。您在
DisplayNodes()
函数和render()
函数中的分解都不正确。您正在数组中而不是数组中查找对象。请将const{noderray}=this.state.noderray
更改为const{noderray}=这个.state
我想你会很好的。没有bug。你在DisplayNodes()
函数和render()
函数中的解构都是不正确的。你在数组中寻找一个对象,而不是数组。更改每个常量{noderray}=this.state.noderray
到justconst{noderray}=this.state
我认为你会很好。除了已经指出的问题(渲染中的错误解构和设置状态)之外,这里重要的是理解如何在react中管理数据
render()
应该只渲染来自状态和道具的数据(返回元素)。修改数据应该在渲染之外进行。我不清楚在本例中,GenerateArray
在做什么。是应该在组件装载时只运行一次,还是希望它运行每个渲染
我以前在ComponentDidMount时有过它,它会计算数组的宽度和高度并创建网格,这在创建网格时起到了作用,不过,最佳实践告诉我,除非是HTTP调用数据,否则不会在ComponentDidMount中设置状态
你基本上只是格式化你的数据,或者在这里计算初始状态。这个逻辑应该放在构造函数中
。把你的计算结果放在This.state={noderray:result,…}
然后你应该问自己,“这个逻辑什么时候应该再次运行?”GenerateGrid
的结果取决于nodeSize
和屏幕尺寸。显然nodeSize
在这里永远不会改变,它可能是一个常数50。screenWidth
和screenHeight
也不会改变,所以我认为在最初进行这些计算之后,您不应该重新运行此逻辑。在这种情况下,您应该将其从渲染中移除。如果希望网格在屏幕尺寸更改时重新计算,则必须为window onResize事件创建侦听器,并在状态中更新新的screenHeight
和screenWidth
,然后在每个渲染中运行此格式化逻辑
同样,非常重要的是要记住,
render
应该只渲染状态和道具中的数据,而您创建的生命周期方法和侦听器应该更改渲染过程中使用的状态,除了已经指出的问题(渲染中的错误解构和设置状态)这里重要的是理解如何在react中管理数据
render()
应该只渲染来自状态和道具的数据(返回元素)。修改数据应该在渲染之外进行。我不清楚在本例中,GenerateArray
在做什么。是应该在组件装载时只运行一次,还是希望它运行每个渲染
我以前在ComponentDidMount时有过它,它会计算数组的宽度和高度并创建网格,这在创建网格时起到了作用,不过,最佳实践告诉我,除非是HTTP调用数据,否则不会在ComponentDidMount中设置状态
你基本上只是格式化你的数据,或者在这里计算初始状态。这个逻辑应该放在构造函数中
。把你的计算结果放在This.state={noderray:result,…}
然后