更改 React 状态会在稍后重新渲染,然后它应该
Changing React state happens a re-render later, then it should
我有一个功能组件管理多个状态,其中包括一个状态,它存储索引,当我单击 suitable 按钮时,我用它呈现一种 table。 OnClick 该按钮调用回调函数,该函数运行点击处理程序。该点击处理程序将索引状态更改为与数组条目相同的 'index',我在其中存储了一个对象,其中包含用于呈现子组件的信息。
我希望 onClick 状态会在渲染发生之前发生变化,因此组件可以正确渲染。然而它只会在稍后渲染时发生。
我已经尝试调用 useEffect-hook 来重新渲染,当索引状态改变时,但这也没有帮助。
这里是代码的简化版本:
export const someComponent = () => {
[index, setIndex] = useState(-1);
const handleClick = (id) => {
setIndex(id);
// This is a function, I use to render the table
buildNewComponent(index);
}
}
进一步 'down' 在代码中,我得到了渲染 table 条目的函数。我在 table 的子组件中传递了 onClick 道具,如下所示:
<SomeEntryComponent
onClick={() => handleClick(arrayEntry.id)}
>
// some code which is not affecting my problem
</SomeEntryComponent>
如前所述:当 onClick 触发时,它会在第二次按下时首先呈现组件,因为首先状态会发生变化。
谁能告诉我为什么会这样,我该如何修复它才能正常工作?
调用 buildNewComponent
时,index
尚未更新。您刚刚调用了 setState,不能保证此后立即更新该值。您可以在此处使用 id
或在具有 index
作为其依赖项的 useEffect 中调用 buildNewComponent
。
我相信如果您使用 useEffect
并监视 index
更改,您可以有正确的行为。
export const someComponent = () => {
[index, setIndex] = useState(-1);
useEffect(() => {
// This is a function, I use to render the table
buildNewComponent(index);
}, [buildNewComponent, index])
const handleClick = (id) => {
setIndex(id);
}
}
过程将是:
- 当用户点击并调用
handleClick
时,它将使用新的 id
调度 setIndex
index
会变成一样的id
useEffect
将看到 index
中的变化并调用 buildNewComponent
。
一件重要的事情是用 useCallback
包裹 buildNewComponent
以避免意外行为。
正如其他人所说,这是一个同步性问题,其中 index
正在更新 在 buildComponent
被调用后。
但从设计的角度来看,最好通过其值断言 index
存在,而不是在处理程序中标记它。我不知道背后的细节buildComponent
,但你可以把它变成组件的条件渲染。
您的组件呈现从其数据派生,而不是手动创建。
export const someComponent = () => {
[index, setIndex] = useState(-1);
const handleClick = (id) => setIndex(id);
const indexHasBeenSelected = index !== -1
return (
<div>
{indexHasBeenSelected && <NewComponent index={index} />}
</div>
)
}
我有一个功能组件管理多个状态,其中包括一个状态,它存储索引,当我单击 suitable 按钮时,我用它呈现一种 table。 OnClick 该按钮调用回调函数,该函数运行点击处理程序。该点击处理程序将索引状态更改为与数组条目相同的 'index',我在其中存储了一个对象,其中包含用于呈现子组件的信息。
我希望 onClick 状态会在渲染发生之前发生变化,因此组件可以正确渲染。然而它只会在稍后渲染时发生。
我已经尝试调用 useEffect-hook 来重新渲染,当索引状态改变时,但这也没有帮助。
这里是代码的简化版本:
export const someComponent = () => {
[index, setIndex] = useState(-1);
const handleClick = (id) => {
setIndex(id);
// This is a function, I use to render the table
buildNewComponent(index);
}
}
进一步 'down' 在代码中,我得到了渲染 table 条目的函数。我在 table 的子组件中传递了 onClick 道具,如下所示:
<SomeEntryComponent
onClick={() => handleClick(arrayEntry.id)}
>
// some code which is not affecting my problem
</SomeEntryComponent>
如前所述:当 onClick 触发时,它会在第二次按下时首先呈现组件,因为首先状态会发生变化。
谁能告诉我为什么会这样,我该如何修复它才能正常工作?
调用 buildNewComponent
时,index
尚未更新。您刚刚调用了 setState,不能保证此后立即更新该值。您可以在此处使用 id
或在具有 index
作为其依赖项的 useEffect 中调用 buildNewComponent
。
我相信如果您使用 useEffect
并监视 index
更改,您可以有正确的行为。
export const someComponent = () => {
[index, setIndex] = useState(-1);
useEffect(() => {
// This is a function, I use to render the table
buildNewComponent(index);
}, [buildNewComponent, index])
const handleClick = (id) => {
setIndex(id);
}
}
过程将是:
- 当用户点击并调用
handleClick
时,它将使用新的id
调度 index
会变成一样的id
useEffect
将看到index
中的变化并调用buildNewComponent
。
setIndex
一件重要的事情是用 useCallback
包裹 buildNewComponent
以避免意外行为。
正如其他人所说,这是一个同步性问题,其中 index
正在更新 在 buildComponent
被调用后。
但从设计的角度来看,最好通过其值断言 index
存在,而不是在处理程序中标记它。我不知道背后的细节buildComponent
,但你可以把它变成组件的条件渲染。
您的组件呈现从其数据派生,而不是手动创建。
export const someComponent = () => {
[index, setIndex] = useState(-1);
const handleClick = (id) => setIndex(id);
const indexHasBeenSelected = index !== -1
return (
<div>
{indexHasBeenSelected && <NewComponent index={index} />}
</div>
)
}