dream boy achyut
dream boy achyut

Reputation: 41

Could not store data in state in react js

I have a two data in cardTypeData :

0: {id: 226, obj: {…}, Slug: 'hello-0'
1: {id: 228, obj: {…}, Slug: 'hello-1'}

useEffect(() => {
      let newcard = [];
      console.log("cardTypeData= ",cardTypeData)
          if (cardTypeData) {
            cardTypeData.map((item) => {
              if(item.Slug){
              const requestUrl = `chartconfig/${item.Slug}/${
                searchQuery?.year
                  ? `?year=${searchQuery.year}${
                      searchQuery.month ? "&month=" + searchQuery.month : ""
                    }`
                  : ``
              }`;
              axiosRequest.get(requestUrl)
              .then((res) => {
                  newcard.push(res.data);
              })
              .catch(console.log('err'))
              // .catch((error)=>{
              //   console.log(error)
              // });
            }
            });
          }
          console.log('list', newcard)
          setCardData(newcard);
      }, [cardTypeData]);

the console output is shown in the figure, how to fix this issues. enter image description here

enter image description here

here data is shown but i could not display it in html.

Upvotes: 0

Views: 99

Answers (3)

user9760669
user9760669

Reputation:

Refactor, refactor, and refactor again. The above solutions overall work as expected, but could be written better. I hope you do not mind if I show you how it should look like.

function loadNewCards() {
  if (!cardTypeData) return

  cardTypeData.forEach(async (cardItem) => {
    if (!cardItem.Slug) return

    const searchParams = new URLSearchParams(searchQuery).toString()
    const requestUrl = `chartconfig/${cardItem.Slug}/${searchParams}`
    const response = await axios.get(requestUrl).catch(console.log)

    if (!response) return

    setCardData(prevCardData => [...prevCardData, response.data])
  })
}

useEffect(() => {
  loadNewCards()
}, [cardTypeData])

Firstly, please avoid nesting. It makes your code less readable. Try to use negation to avoid nested if / else statement.

if (!cardItem.Slug) return

would be better than

if (item.Slug) {
   const requestUrl = `chartconfig/${item.Slug}`

Secondly, please use URLSearchParams to build the query params. This class will handle your object that contains year and month. I think it is better to have

const searchParams = new URLSearchParams(searchQuery).toString()
const requestUrl = `chartconfig/${cardItem.Slug}/${searchParams}`

instead of

const requestUrl = `chartconfig/${item.Slug}/${
  searchQuery?.year
    ? `?year=${searchQuery.year}${
      searchQuery.month ? '&month=' + searchQuery.month : ''
    }`
    : ``
}`

Upvotes: 2

Kritish Bhattarai
Kritish Bhattarai

Reputation: 1661

Network request is asynhcronous. Before newcard.push(res.data) runs, setCardData(newcard) is already executed with initialized value of newcard which is [ ], ...you can modify the code something similar as below to make it work

useEffect(() => {
      // let newcard = [];
      console.log("cardTypeData= ",cardTypeData)
          if (cardTypeData) {
            cardTypeData.map((item) => {
              if(item.Slug){
              const requestUrl = `chartconfig/${item.Slug}/${
                searchQuery?.year
                  ? `?year=${searchQuery.year}${
                      searchQuery.month ? "&month=" + searchQuery.month : ""
                    }`
                  : ``
              }`;
              axiosRequest.get(requestUrl)
              .then((res) => {
                   
                  ***** modified 👇*****
                  // newcard.push(res.data);
                  setCardData(prev => [...prev, res.data])
              })
              .catch(console.log('err'))
              // .catch((error)=>{
              //   console.log(error)
              // });
            }
            });
          }
          console.log('list', newcard)
          // setCardData(newcard);
      }, [cardTypeData]);

Upvotes: 1

Domotor Zsolt
Domotor Zsolt

Reputation: 634

I've read somewhere that console.log doesn't always run the exact time you call it, sometimes it waits a bit especially when you expand the input.

The problem might be from the api calls from the cardTypeData.map.

Try using for instead to test it out. Also you will have to extract the async part because React doesn't like async useEffect..

Something like this:

const loadNewCards = async () => {
let newcard = [];
console.log("cardTypeData= ", cardTypeData);
if (cardTypeData) {
    for (let item of cardTypeData) {
  if (!item.Slug) {
    const requestUrl = `chartconfig/${item.Slug}/${
      searchQuery?.year
        ? `?year=${searchQuery.year}${
            searchQuery.month ? "&month=" + searchQuery.month : ""
          }`
        : ``
    }`;
    await axiosRequest
      .get(requestUrl)
      .then((res) => {
        newcard.push(res.data);
      })
      .catch(console.log("err"));
  }
}
}
console.log("list", newcard);
setCardData(newcard);
};
useEffect(() => {
    loadNewCards();
}, [cardTypeData]);

And if you worried about performance you should use Promise.all to run all the calls in parallel.

Upvotes: 1

Related Questions