如何在不使用状态变量的情况下实现实时重新渲染?

How do I achieve live re-render without using state variables?

考虑以下对象数组:

const tasks = [
    {
      text: "Finish this page",
      deadline: new Date("05/01/2022"),
      status: "complete",
      // ToDo: Add priority fields
    },
    {
      text: "Finish Pierian UI/UX",
      deadline: new Date("05/10/2022"),
      status: "incomplete",
    },
    {
      text: "Finish Internship",
      deadline: new Date("05/05/2022"),
      status: "incomplete",
    },
    {
      text: "Anaadyanta",
      deadline: new Date("05/12/2022"),
      status: "incomplete",
    },
    {
      text: "Random task",
      deadline: new Date("05/19/2022"),
      status: "incomplete",
    },
  ];

考虑以下函数:

{tasks.map((element) => {
        return (
          <p
            key={element.name}
            className={element.status === "complete" && "strike"}
            style={{ borderLeft: "2px solid red" }}>
            <Checkbox
              size="small"
              onClick={() => {
                if (element.status === "incomplete")
                  element.status = "complete";
                else if (element.status === "complete") {
                  element.status = "incomplete";
                }
                // ToDo : Add few things like popping
              }}
              color="success"
              checked={element.status === "complete" && true}
            />
            {element.text}
          </p>
        );
      })}

现在因为 element.status 不是一个状态,改变它的值不会重新渲染 JSX 元素。我如何实现这一目标?我想过使用状态变量,但是当状态变量改变时会反映所有渲染元素的变化,而不仅仅是当前元素。

你不能 - 至少,不能以任何好的方式。 React 确定何时需要 re-render 的 方式是在调用状态 setter 时。

React 应用程序应该尽可能让应用程序的外观尽可能多地来自状态。也就是说,理想情况下,给定所有组件的状态,您应该能够确定正在呈现给用户的所有内容。

I thought of using a state variable, but that when changed would reflect changes in all rendered elements and not only the current element.

为什么它一定会改变所有元素?只需更改被迭代的一个元素。为了使事情更容易,使用 complete: boolean 而不是 status: 'complete' | 'incomplete'

const [tasks, setTasks] = useState([
    {
      text: "Finish this page",
      deadline: new Date("05/01/2022"),
      complete: true
      // ToDo: Add priority fields
    },
    // ...
]);
// ...
{tasks.map((element, i) => {
    ...
    onClick={() => {
        setTasks(tasks.map(
            (task, j) => i === j ? { ...task, complete: !element.complete } : task
        );
    }}