更改 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);    
  }
}

过程将是:

  1. 当用户点击并调用 handleClick 时,它将使用新的 id
  2. 调度 setIndex
  3. index会变成一样的id
  4. 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>
    )
}