繁体   English   中英

使用 useState 存储对象数组的 state

[英]Using useState to store state for an array of objects

我正在处理从这里https://jsonplaceholder.typicode.com/users获取数据。 这将返回一个对象数组,我希望将其存储在我的 useState 挂钩中。 我现在尝试的是这样的:

import React, { useState, useEffect } from "react";

const UserList = () => {
  const [data, setData] = useState([
    {
      id: "",
      email: "",
      website: "",
      phone: "",
      name: ""
    }
  ]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => response.json())
      .then((json) => {
        console.log(json);
        json.map((object) => {
          setData((data) => [
            ...data,
            {
              id: object.id,
              email: object.email,
              website: object.website,
              phone: object.phone,
              name: object.name
            }
          ]);
        });
      });
  }, []);

  return (
    <>
      <div>
        <ul>
          {data.map((info) => {
            <li key = {info.id}></li>;
          })}
        </ul>
      </div>
    </>
  );
};

export default UserList;

我觉得我在使用扩展运算符存储数据时犯了一些错误,因为 console.log 显示。 当我在 data.map function 中放置一个 console.log(info) 时,它会继续重复这十个对象。 我有点不确定这部分代码到底是如何工作的,所以如果有人可以提供任何建议或任何有用的东西。

删除json.map并放置此代码

setData((data) => [
  ...data,
  ...json.map(({id, email, website, phone, name}) => ({
    id,
    email,
    website,
    phone,
    name
  })),
]);

扩展语法 (...) 允许在预期零个或多个 arguments(用于 function 调用)或元素(用于数组文字)的地方扩展诸如数组表达式或字符串之类的可迭代对象,或者在表达式中扩展 ZA8CFDE6331BD59EB666F8911需要零个或多个键值对(对于 object 文字)的地方。 - 传播语法

当您使用...时,您会将右侧的所有内容复制到一个新变量中。 如果它与数组[...items]一起使用,它会将数组中的所有项目复制到名为items的数组变量中。 如果它是 object {...item}它会将 object 的字段复制到名为item的变量 object 中。

在您调用setData时的代码中, data变量是data的当前/先前值,即:

[
    {
      id: "",
      email: "",
      website: "",
      phone: "",
      name: ""
    }
  ]

由于您在此处设置的初始默认值:

  const [data, setData] = useState([
    {
      id: "",
      email: "",
      website: "",
      phone: "",
      name: ""
    }
  ]);

这意味着您将该数组复制到具有新 object 的新数组中。

// for each json object
json.map((object) => {
         // update the data by: 
          setData((data) => [
            ...data, // copying the current data into this array
            { // and adding this new object
              id: object.id,
              email: object.email,
              website: object.website,
              phone: object.phone,
              name: object.name
            }
          ]);
        });

但这是在map内部调用setData ,因此 json 的每个元素都将重复上述过程,这并不理想。 相反,如果您可以调用一次setData会更好。 通过将 json 映射到您想要的字段,然后合并或发布其他提供的建议。

  // map to the fields we're interested in using
  const newData = json.map(object => ({
    //  only use these fields for newData
    id: object.id,
    email: object.email,
    website: object.website,
    phone: object.phone,
    name: object.name,
  }));

  // copy the existing previous data with the new data we just fetched
  setData(previousData => [...previousData, ...newData]);

上面这个要好得多,如果它被多次调用,可能会有重复的机会,但由于它的效果没有任何依赖关系,它只会在挂载时被调用一次。 如果您希望此获取发生一次并确定您确实不需要为数据设置的初始默认值,您可以摆脱对...传播/合并的需要

  // we decided we didn't need the default obj
  const [data, setData] = useState([]);
  // map to the fields we're interested in using
  const newData = json.map(object => ({
    //  only use these fields for newData
    id: object.id,
    email: object.email,
    website: object.website,
    phone: object.phone,
    name: object.name,
  }));
  setData(newData)

列表渲染还有其他问题。 您没有返回任何内容,因此它会呈现null的列表,并且没有显示任何内容,因此您需要确保它返回一些内容:

        <ul>
          {id}
          // this function returns undefined 
          {data.map((info) => {
            <li key={info.id}></li>;
          })}
          // this function returns
          {data.map((info) => {
            return <li key={info.id}></li>;
          })}
          // or return it with arrow implicitly           
          {data.map((info) => <li key={info.id}></li>)}
        </ul>

最初声明const [data, setData] = useState([]); 并将返回元素li包裹在括号内。 请参阅下面的工作代码,

import React, { useState, useEffect } from "react";

const UserList = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => response.json())
      .then((json) => {
        console.log(json);
        json.map((object) => {
          setData((data) => [
            ...data,
            {
              id: object.id,
              email: object.email,
              website: object.website,
              phone: object.phone,
              name: object.name
            }
          ]);
        });
      });
  }, []);

  return (
    <>
      <div>
        <ul>
          {data.map((info) => (
            <li key = {info.id}>{info.id}</li>
          ))}
        </ul>
      </div>
    </>
  );
};

export default UserList;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM