状态更新不影响视图

state update not affecting on view

我正在做一个基本的 React 项目,我在其中对对象和数组进行反应状态,我想在这里完成的是我想将对象推送到 images 数组,我想在组件中呈现它,到目前为止,我用谷歌搜索了一些东西,我发现很少有方法可以完成它 array.concatarray.push,我尝试了这两种方法它正在更新状态但它不影响组件

下面是我试过的代码

const [proClrData, setProClrData] = useState([
  { color: "black", price: "", qty: "", images: [] },
  { color: "white", price: "", qty: "", images: [] },
  { color: "red", price: "", qty: "", images: [] }
]);
const addImages = (key) => {
  var obj = { src: "", imgdata: "" };
  proClrData[key].images = proClrData[key].images.concat(obj);
  console.log(proClrData);
 };

下面是组件代码

 {proClrData.length >= 1 &&
    proClrData?.map((clr, key) => {
      return (
        <div key={key}>
          <p className="pt-3 ">{clr.color}</p>
          <div className="form-group">
            <input
              label="Price"
              name="price"
              value={clr?.price}
              type="number"
              fullWidth
              required
            />
          </div>
          <div className="form-group pt-3">
            <input
              label="Quantity"
              name="qty"
              value={clr?.qty}
              type="number"
              fullWidth
              required
            />
          </div>
          <div className="text-end pt-3">
            <button
              variant="contained"
              color="primary"
              onClick={() => addImages(key)}
            >
              Add Images
            </button>
          </div>
          {clr?.images?.map((img, imgkey) => {
            return (
              <div className="form-group pt-3" key={imgkey}>
                <input
                  label="Image"
                  name="images"
                  value=""
                  accept="image/*"
                  type="file"
                  fullWidth
                  required
                />
              </div>
            );
          })}
        </div>
      );
    })}

这里是 codeSandbox 的工作代码。

您应该相应地修改 proClrData 并使用 setProClrData 以触发重新渲染。

查看文档:https://reactjs.org/docs/hooks-state.html

你直接更新状态

为此使用函数:

setProClrData(prev => prev.push() // or concat)

您必须调用 setProClrData 函数来更新状态。

记住你不能改变状态,相反你必须提供一个新的引用(在你的例子中是一个新数组)并调用更新函数,否则 React 将不知道应该重新渲染组件。

const [proClrData, setProClrData] = useState([
  { color: "black", price: "", qty: "", images: [] },
  { color: "white", price: "", qty: "", images: [] },
  { color: "red", price: "", qty: "", images: [] }
]);

const addImages = (key) => {
  const img = { src: "", imgdata: "" };
  const newProClrData = proClrData.map((obj, index) => {
    return index !== key ? data : { ...obj, images: [...data.images, img] };
  });
  setProClrData(newProClrData);
 };

问题

您正在改变状态对象,然后 根本 不更新状态。

const addImages = (key) => {
  var obj = { src: "", imgdata: "" };
  proClrData[key].images = proClrData[key].images.concat(obj); // mutation!!
  console.log(proClrData);
};

解决方案

使用您想要的新图像数据对状态更新进行排队。使用功能状态更新从以前的状态更新。浅拷贝 proClrData 数组,对于匹配的元素,也浅拷贝它所以它是一个新的对象引用,然后浅拷贝嵌套的 images 数组并追加新对象。

const [proClrData, setProClrData] = useState([
  { color: "black", price: "", qty: "", images: [] },
  { color: "white", price: "", qty: "", images: [] },
  { color: "red", price: "", qty: "", images: [] }
]);

const addImages = (key) => {
  const obj = { src: "", imgdata: "" };
  setProClrData(data => data.map((el, i) => i === key ? {
    ...el,
    images: [...el.images, obj],
  } : el));
};

由于 React 状态更新是异步处理的,您需要将控制台日志移动到 useEffect 挂钩中以记录状态 它更新后可用下一个渲染。

useEffect(() => {
  console.log(proClrData);
}, [proClrData]);