更新状态变量作为道具传递后反应不重新渲染子组件

分享于2022年09月08日 reactjs 问答
【问题标题】:React not re-rendering child component after updating state var passed as prop更新状态变量作为道具传递后反应不重新渲染子组件
【发布时间】:2022-08-02 09:33:56
【问题描述】:

我正在编写一个简单的“像素艺术”绘画程序,只是为了好玩。我已经让绘画部分工作了,但是我想要一个按钮来将画布的“像素”重置为其原始颜色,我想我一定是对 React 渲染的工作方式有一些误解。

我在下面包含了一个非常简化的代码版本。当您单击红色单元格并将其“绘制”为粉红色,然后单击“重置”按钮时,我期望会发生以下情况:

<1234564> <1234563>Grid 组件的 resetPaint 状态变量从 false 更改为 true <1234563>这会导致将 resetPaint 设置为 true 的网格重新渲染<1234563>自从 resetPaint 被传递给 Cell,Cell 的 props 现在已经改变,所以它重新渲染(或者至少在 VDOM 中得到了差异?)<1234563>Cell 中的 if (resetPaint)... 逻辑使其恢复为默认颜色,从而导致它在 DOM 中重新渲染<1234563>Cell 渲染后,我们用 resetPaint && setResetPaint(false) 重置resetPaint

查看 console.log 语句,看起来正在发生的事情更像这样:

<1234564> <1234563>Grid 组件的 resetPaint 状态变量从 false 更改为 true <1234563>这会导致重新渲染 Grid 并将 resetPaint 设置为 true <1234563>细胞确实 不是 重新渲染<1234563>我们用 resetPaint && setResetPaint(false) 重置resetPaint<1234563>网格再次渲染,这次将 resetPaint 设置为 false <1234563> 现在 单元格重新渲染,但是因为 resetPaint 为 false,所以颜色没有改变

我假设第二个 Grid 渲染是由于 setResetPaint(false) 造成的,虽然如果可以避免这种情况会很好,因为我知道它不会(或不应该)改变任何东西,主要是我对为什么 Cell 不”感到困惑t 在 resetPaint 设置为 true 后重新渲染,但在设置为 false 后重新渲染。

我希望这意味着我正处于探索 React 的某些方面的边缘,而我显然还没有探索;有人可以帮我到那里吗?

import React from 'react';

export const Cell = ({  defaultColor, selectedColorRef, resetPaint}) => {
  const [color, setColor] = React.useState(defaultColor)
  const onClick = () => setColor(selectedColorRef.current);
  React.useEffect(() => {
    if (resetPaint) {
    setColor(defaultColor);
   }
  }, [resetPaint]);
  console.log(`Cell rendering with resetPaint=${resetPaint} and color=${color} (${defaultColor})`); 
  return 
} export const Grid = () => { // Denotes the selected color in the color palette (palette omitted here for simplicity) const selectedColorRef = React.useRef('pink'); // Supposed to trigger a re-render with original color const [resetPaint, setResetPaint] = React.useState(false); console.log(`Grid rendering with resetPaint=${resetPaint}`); const grid = (
{/* Normally the drawing "canvas" would be a grid of Cells like this, but we'll just include one for simplicity. */}
) // Tried moving this to a useEffect based on changes to resetPaint, in case the issue was // that this update was taking place before Cell had finished rendering, but it caused an // infinite re-render loop resetPaint && setResetPaint(false); return grid; }

    <1234563>
    如果您可以为此创建一个代码框,那将会有所帮助

【解决方案1】:

如果孩子从父母那里得到 props ,你应该在 useEffect 中设置统计信息,如果你做了类似打击之类的事情,它不会在道具更改后更新

export default const Child(props) {
    const [state, setState ] = useState(props.state);
    
}

这不起作用,所以你应该使用结构打击

export default const Child(props) {
    const [state, setState ] = useState(null);
    useEffect(() => {
    setState(props.state);
}, [props]);
}

【讨论】: