React:使 JSON 对象具有反应性,使 JSON 对象内的属性具有反应性,在变化时更新 div

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

小提琴:https://codesandbox.io/s/modern-tree-27z3q2?file=/src/App.js

我有非常简单的代码显示数组中的所有元素

animals
(它只有一个 JSON 对象:
{'name': 'A', 'kind': 'dog'}
.

单击按钮时,

name
将更改为
Better Name
值。但是,显示的数据不会更新。

App.js:

import "./styles.css";
import React, { useEffect, useState } from "react";

export default function App() {
  let [animals, setAnimals] = useState([]);

  useEffect(() => {
    let temp = [];

    temp.push({ name: "A", kind: "dog" });

    setAnimals(temp);
  }, []);

  async function changeAnimalName(animal) {
    animal.name = "Better Name";

    alert(JSON.stringify(animals[0]));
  }

  return (
    <div className="App">
      {animals.map((animal) => (
        <div>
          <b>{animal.name}</b> is a <b>{animal.kind}</b>
          <div
            style={{
              marginTop: "1em",
              backgroundColor: "green",
              padding: "1em",
              borderRadius: "2em"
            }}
            onClick={() => {
              changeAnimalName(animal);
            }}
          >
            Change Name
          </div>
        </div>
      ))}
    </div>
  );
}

在我点击

Change Name
按钮后,我收到这个警告消息:

所以

name
数组中第一个JSON对象的
animals
被改变了,但是页面仍然显示:

我来自

Vue
,那里的更新是自动的。我看到在反应中
useState
用于管理反应性,但是我不确定如何为已经存在的
JSON
对象做到这一点。

javascript reactjs react-hooks
1个回答
1
投票

正如我在评论中提到的,你不能那样更新状态;

animals
只是状态的快照,它不能被改变。

useState
Hook 提供了两件事:

  • 一个状态变量来保留渲染之间的数据。
  • 一个状态设置函数,用于更新变量并触发 React 再次渲染组件。

解决方案

工作代码:https://codesandbox.io/s/modest-sun-k7suvt?file=/src/App.js

import "./styles.css";
import React, { useEffect, useState } from "react";

export default function App() {
  let [animals, setAnimals] = useState([]);

  useEffect(() => {
    let temp = [];

    temp.push({ name: "A", kind: "dog" });

    setAnimals(temp);
  }, []);

  async function changeAnimalName(index) {
    setAnimals((animalsArr) => {
      return animalsArr.map((animal, i) => {
        if (index === i) {
          animal.name = "Better Name";
        }

        return animal;
      });
    });
  }

  return (
    <div className="App">
      {animals.map((animal, i) => (
        <div>
          <b>{animal.name}</b> is a <b>{animal.kind}</b>
          <div
            style={{
              marginTop: "1em",
              backgroundColor: "green",
              padding: "1em",
              borderRadius: "2em"
            }}
            onClick={() => {
              changeAnimalName(i);
            }}
          >
            Change Name
          </div>
        </div>
      ))}
    </div>
  );
}


说明

我正在发送我想要变异的动物的索引;通常,这应该是一个唯一的 ID,但在这个简单的示例中,这应该可以正常工作。

然后,我更新状态:

setAnimals((animalsArr) => {
  return animalsArr.map((animal, i) => {
    if (index === i) {
      animal.name = "Better Name";
    }

    return animal;
  });
});

所以我根据索引找到了正确的动物,并在里面进行了更改

setAnimals
。请记住,每当您想更新
setAnimals
状态
时,都必须致电
animals

进一步阅读

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