简体   繁体   English

无法在反应 js 中以状态存储数据

[英]Could not store data in state in react js

I have a two data in cardTypeData :我在 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.控制台输出如图所示,如何解决这个问题。 在此处输入图片说明

在此处输入图片说明

here data is shown but i could not display it in html.这里显示了数据,但我无法在 html 中显示它。

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/else 语句。

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.其次,请使用 URLSearchParams 构建查询参数。 This class will handle your object that contains year and month .此类将处理包含yearmonth对象。 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 : ''
    }`
    : ``
}`

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 worknewcard.push(res.data)运行之前, setCardData(newcard)已经用 newcard 的初始化值执行了,即 [ ],...你可以修改类似于下面的代码以使其工作

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

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.我在某处读到 console.log 并不总是在您调用它的确切时间运行,有时它会等待一段时间,尤其是当您展开输入时。

The problem might be from the api calls from the cardTypeData.map.问题可能来自 cardTypeData.map 的 api 调用。

Try using for instead to test it out.尝试使用for来测试它。 Also you will have to extract the async part because React doesn't like async useEffect..您还必须提取异步部分,因为 React 不喜欢异步 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.如果您担心性能,您应该使用Promise.all并行运行所有调用。

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

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