Home > Enterprise >  How to Store and Update then again store in useState
How to Store and Update then again store in useState

Time:10-20

I'm using here useState to store data, update current value, by using this it's not store previous data, it's only store update current value which do useState. But I want to store previous data and update data all of them, somethings like, i have 10 api's data and i want to call them end of my api using ids.

i want to store 10 api's data in one array.

how to store 10 apis data in together using useState();

my code is somethings like:

const [dataLoc, setDataLoc] = useState([]); 
const ids = [1,2,3,4,5,6,7,8,9,10]
useEffect(() => {
        ids?.map((id) => {
            fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
                .then((response) => response.json())
                .then((dataLoc) => setDataLoc(dataLoc.title))
                .catch((error) => console.error(error))
        })
    }, []);

    console.log(dataLoc);

output is:

enter image description here

but it's in 10 array the out put but i want all the title in one array.

anyone can help me how can i do this here? ThankYou for Your Trying in advance!

CodePudding user response:

You can make use of react states prev-callback like that:

const [dataLoc, setDataLoc] = useState([]);

useEffect(() => {
  ids?.map((id) => {
    fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
      .then((response) => response.json())
      .then((dataLoc) => setDataLoc((prev) => [...prev, dataLoc.title]))
      .catch((error) => console.error(error));
  });
}, []);

console.log(dataLoc);

By spreading ...prev and appending it with , dataLoc.title you add each entry to the previous state value. The order is the one in which the calls go through, since we insert the new element at the end.

Edit

If you want to console.log multiple times you can make use of another useEffect inside your component:

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

CodePudding user response:

Issue

The code is enqueueing state updates in a loop and not updating from the previous state. In other words, each enqueued update in the loop overwrites the previous update. The update from the last loop iteration is the one the app sees on the subsequent render.

Solution

Either use a functional state update to correctly enqueue state updates and update from the previous state. Use .forEach instead of .map.

const [dataLoc, setDataLoc] = useState([]);

useEffect(() => {
  ids?.forEach((id) => {
    fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
      .then((response) => response.json())
      .then((dataLoc) => setDataLoc(dataLoc => [...dataLoc, dataLoc.title]))
      .catch((error) => console.error(error))
  })
}, []);

Or map the ids to an array of Promises and Promise.all them and enqueue a single state update.

const [dataLoc, setDataLoc] = useState([]);

useEffect(() => {
  const requests = ids?.map((id) => {
    return fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
      .then((response) => response.json())
      .then((dataLoc) => return dataLoc.title)
      .catch((error) => console.error(error))
  });

  Promise.all(requests)
    .then(ids => {
      setDataLoc(ids)
    });
}, []);

CodePudding user response:

In your case it is overriding the previous values. You can merge the values

React.useEffect(() => {
    ids?.map((id) => {
      fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
        .then((response) => response.json())
        .then((dataLoc) =>
          setDataLoc((prevState) => {
            return [...prevState, dataLoc.title];
          })
        )
        .catch((error) => console.error(error));
    });
  }, []);

CodePudding user response:

you can use push method to add each title to the Array:

    const [dataLoc, setDataLoc] = useState([]); 
    const ids = [1,2,3,4,5,6,7,8,9,10]
    useEffect(() => {
    ids?.map((id) => {
        fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
            .then((response) => response.json())
            .then((dataLoc) => setDataLoc(dataLoc.push(dataLoc.title)))
            .catch((error) => console.error(error))
    })
}, []);

console.log(dataLoc);
  • Related