admin管理员组

文章数量:1277322

I am working with react and fetching data from here, . This returns an array of objects and I was hoping to store it in my useState hook. What I have tried right now is this:

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

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

  useEffect(() => {
    fetch(";)
      .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;

I feel I am making some mistakes while using the spread operator to store the data as a console.log reveals. When I place a console.log(info) in the data.map function, it keeps on repeating the ten objects. I am a little unsure exactly how that part of the code is working so if anyone can offer any suggestions or anything that would be helpful.

I am working with react and fetching data from here, https://jsonplaceholder.typicode./users. This returns an array of objects and I was hoping to store it in my useState hook. What I have tried right now is this:

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

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

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode./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;

I feel I am making some mistakes while using the spread operator to store the data as a console.log reveals. When I place a console.log(info) in the data.map function, it keeps on repeating the ten objects. I am a little unsure exactly how that part of the code is working so if anyone can offer any suggestions or anything that would be helpful.

Share Improve this question edited Feb 27, 2021 at 20:10 skyboyer 23.8k7 gold badges62 silver badges71 bronze badges asked Feb 27, 2021 at 13:08 TanDevTanDev 4373 gold badges8 silver badges15 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

Spread syntax (...) allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected. - spread syntax

When you use ... you copy everything thats on the right into a new variable. If it's used with an array [...items] it copies all the items in the array to an array variable named items. If it's an object {...item} it copies the fields of the object to a variable object named item.

In your code when you call setData, the data variable is the current/previous value of data, which is this:

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

because of the initial default value that you set it as here:

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

This means you're copying that array into a new array with a new 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
            }
          ]);
        });

But this is calling setData inside of a map so each element of json will repeat the process above and that is not ideal. Instead it's better if you can call setData once. By mapping json to the fields you want and then merging or the other provided suggestions posted.

  // 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]);

This above is much nicer, if this were called multiple times there might be chance for duplicates, but since its in an effect without any dependencies it only gets called once on mount. If you're expecting this fetch to happen once and decide that you really don't need the initial default you set for data you can get away with removing the need for ... spread/merging

  // 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)

Theres also this other issue you have with the list rendering. You're not returning anything so it renders a list of null and that doesn't show anything so you need to make sure it returns something:

        <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>

remove json.map and place this code

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

Initially declare const [data, setData] = useState([]); and wrap the return element li inside parentheses. See working code below,

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

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

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode./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;

本文标签: javascriptUsing useState to store state for an array of objectsStack Overflow