反应状态/在组件之间传递信息

问题描述 投票:0回答:1

我对 React(以及一般的 Web 开发)还很陌生,所以希望我能很好地解释我想要做什么。

为了练习使用状态,我正在构建一个包含 3 个组件的小型应用程序。最小的组件 (Square.jsx) 是一个正方形 (div),当您单击它时可以更改为不同的颜色。下一个组件 (GroupOfSquares.jsx) 循环 x 次并将这些方块推送到空数组中。现在我只是循环 5 次(所以它只是显示一行 5 个变色方块)。该组件中还有一个元素,显示您单击任何方块的总次数,并带有“重置”按钮,该按钮将重置单击的次数。

我真正遇到困难的是这个重置部分。我希望按钮也能重置颜色,但我怎么也想不出来。

代码在这里

我尝试将设置颜色的状态提升到其父组件,但它总是将每个方块渲染为相同的颜色,并且当我单击一个方块时,它们都会同时更改。我之所以这么认为,是因为当我将其移动到 GroupOfSquares 组件中时,我实际上是将状态设置为应用于整个方块组。我认为问题可能在于创建一个渲染 5 个方块的循环,但经过修改后,我认为这与它没有任何关系。我还尝试在父组件中添加额外的状态,同时保留 Square 组件,但这也效果不佳。

我将不胜感激任何为我指明正确方向的建议!

reactjs
1个回答
0
投票

提升状态是正确的,但我认为您错过的是状态需要成为颜色数组,而不仅仅是单个颜色。另外,如果您想重置为完全相同的随机颜色,您需要记住这些颜色是什么。记住随机颜色的一种选择是拥有一个永远不会改变的不同状态:

const [initialColors] = useState(
  Array.from({ length: 5 }).map(() => randomPick(colors)
)
const [colors, setColors] = useState(initialColors);

但是由于您没有更改它,所以还有其他选择。你可以把它记在参考文献中:

const initialColors = useRef(
  Array.from({ length: 5 }).map(() => randomPick(colors)
);
const colors, setColors = useState(initialColors.current);

或者您可以将

useMemo
与空依赖项数组一起使用:

const initialColors = useMemo(() => {
  return Array.from({ length: 5 }).map(() => randomPick(colors))
}, []);
const [currentColors, setCurrentColors] = useState(initialColors)

就我个人而言,我可能会做

memo
版本,但没有太大区别。无论您选择哪一个,您都将根据该数组更改框:

const boxes = currentColors.map((color, i) => (
  <Square
    key={i}
    color={color}
    onClick={() => {
      setCurrentColors((prev) => {
        const next = [...prev]; //
        next[i] = randomPick(colors);
        return next;
      });
      setCount((prev) => prev + 1);
    }}
  />
));

// In Square.js:
function Square({ color, onClick }) {
  return (
    <div
      onClick={onClick}
      className="Square"
      style={{ backgroundColor: color }}
    />
  );
}

要重置,您可以将计数设置为 0,将颜色设置为初始颜色

const reset = () => {
  setCount(0);
  setColors(initialColors);
  // Or if you used a ref:
  // setColors(initialColors.current);
}

沙盒链接:https://codesandbox.io/p/sandbox/intelligent-jang-forked-3kknxy?file=%2Fsrc%2FGroupOfSquares.js

© www.soinside.com 2019 - 2024. All rights reserved.