将状态应用于React中的嵌套对象。我如何称呼API并以使用效果显示

发布于 2025-01-18 04:05:47 字数 1957 浏览 0 评论 0原文

因此,我一直在重新迭代我的代码并使用它几个小时,我需要帮助。我的目标是使用 useEffect 从星座 API 加载 API 调用。我遇到了这个错误,只有在从网站加载另一个页面并重新渲染主页后才能看到数据。我的目标是查看当我调用 useEffect() 时最初显示的数据。然而,这似乎不起作用。不确定我是否需要使用 setInitialState,或者操纵我通过上下文导出值的方式。

进一步推测, 我在某种程度上看到了我的代码中的问题所在,但我不知道如何使用 setInitialState 从 api 加载值。

          initialState.data.yesterday = data;

我是否将其保存到变量然后调用该变量的设置数据?

1.) 我尝试尽我所能地操纵状态。

2.) 页面在第一次运行时从不从 API 加载数据,仅在单击按钮后显示数据

3.) 代码似乎需要 setInitialDate 但找不到与 useEffect< 混合的合理解决方案/code> 以获得正确的数据。

谢谢你!!

我愿意听到针对我的问题的所有最佳解决方案。我什至不确定我是否走在正确的方向上。谢谢。


const [initialState, setInitialState] = useState({
    data: {
        yesterday: {},
        today: {},
        tomorrow: {},
    }
});

useEffect(() => {
    console.log("useEffect called");
    // eslint-disable-next-line react-hooks/exhaustive-deps
    async function getDayInfos() {
        try {
            const response = await axios.post('https://aztro.sameerkumar.website/?sign=aries&day=yesterday');
            const data = response.data
            initialState.data.yesterday = data;
        } catch (error) {
            console.error(error);
        }


        try {
            const response = await axios.post('https://aztro.sameerkumar.website/?sign=aries&day=today');
            initialState.data.today = response.data
        } catch (error) {
            console.error(error);
        }

        try {
            const response = await axios.post('https://aztro.sameerkumar.website/?sign=aries&day=tomorrow');
            initialState.data.tomorrow = response.data
        } catch (error) {
            console.error(error);
        }
    }

    getDayInfos()
    // eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

return <AstroContext.Provider value={{initialState}}>
    {children}
</AstroContext.Provider>

}

So I have been re-iterating my code and working around with it for a few hours and I need help. My goal was to use useEffect to load an API call from a horoscope API. I ran into this error where I was only able to see the data AFTER I loaded another page from the website and re-rendered the homepage. My goal was to see the data displayed initially on useEffect() from when I called it. However, it seems to not work. Not sure if I need to use setInitialState, or manipulate the way I am exporting the values through context.

On further speculation,
I somewhat see what the problem is in my code, but I have no idea HOW to use setInitialState to load values in from the api.

          initialState.data.yesterday = data;

Do I save this to the a variable then call set data on that variable?

1.) I tried manipulating state best I could could.

2.) Page never loads data from API on first run, only shows data after I click a button

3.) Code seems to need setInitialDate but can't find reasonable solution mixed with useEffect to get the data right.

Thank you!!

I am willing to hear all optimal solutions for my problem. I am not even sure if I am going in the right direction. Thanks.


const [initialState, setInitialState] = useState({
    data: {
        yesterday: {},
        today: {},
        tomorrow: {},
    }
});

useEffect(() => {
    console.log("useEffect called");
    // eslint-disable-next-line react-hooks/exhaustive-deps
    async function getDayInfos() {
        try {
            const response = await axios.post('https://aztro.sameerkumar.website/?sign=aries&day=yesterday');
            const data = response.data
            initialState.data.yesterday = data;
        } catch (error) {
            console.error(error);
        }


        try {
            const response = await axios.post('https://aztro.sameerkumar.website/?sign=aries&day=today');
            initialState.data.today = response.data
        } catch (error) {
            console.error(error);
        }

        try {
            const response = await axios.post('https://aztro.sameerkumar.website/?sign=aries&day=tomorrow');
            initialState.data.tomorrow = response.data
        } catch (error) {
            console.error(error);
        }
    }

    getDayInfos()
    // eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

return <AstroContext.Provider value={{initialState}}>
    {children}
</AstroContext.Provider>

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感情洁癖 2025-01-25 04:05:47

React需要您调用setter(例如setInitialState)才能知道您已经更改了可能需要重新渲染的内容。

我知道当您的状态中有嵌套字段时,尝试进行对象操作是很诱人的,但考虑到您的字段基本上是一次性更改的,我们可以原子地执行此操作缩短您的时间 -到第一个有意义的数据。

顺便说一句,我认为 initialState 对于变量名称来说可能不是一个好主意。我们将其称为 dayInfo 因为它就是这样的。我们还需要在加载数据时表示应用程序的状态 - 您将能够显示加载 UI,您可以摆脱空的 useEffect() code> dependency-array (以及 ESLint 禁用注释),它也确实有助于调试。

言归正传,这是一个工作版本:

// Document the shape of our state:
const initialState = {
  yesterday: {},
  today: {},
  tomorrow: {}
};

// Helper function that just gets a single day (to avoid repetition)
const fetchDay = async (day) => {
  try {
    const response = await axios.post(
      `https://aztro.sameerkumar.website/?sign=aries&day=${day}`
    );
    return response.data;
  } catch (error) {
    console.error(error);
  }
};

export default function App() {
  const [loadingState, setLoadingState] = useState("NOT_LOADED");
  const [dayInfo, setDayInfo] = useState(initialState);

  useEffect(() => {
    // Only go fetch the data if we haven't tried to yet
    if (loadingState === "NOT_LOADED") {
      setLoadingState("IN_PROGRESS");
      getDayInfos();
    }
  }, [loadingState]);

  async function getDayInfos() {
    // Fire off the three requests concurrently ...
    const yesterdayPromise = fetchDay("yesterday");
    const todayPromise = fetchDay("today");
    const tomorrowPromise = fetchDay("tomorrow");

    // ... but wait for them all to resolve here
    const [yesterday, today, tomorrow] = await Promise.all([
      yesterdayPromise,
      todayPromise,
      tomorrowPromise
    ]);

    setDayInfo({ yesterday, today, tomorrow });
    setLoadingState("LOADED");
  }

  ...
}

我们现在已经明确何时我们将去获取数据。

我们还更有效地使用 Promise,同时触发三个 Axios 获取,而不是逐一触发。最后,我们以原子方式设置 dayInfo 的状态,并指示我们已获取数据,以避免再次获取它 - 比空依赖项数组安全得多。

React needs you to call the setter (e.g. setInitialState) in order to know that you've changed something that might require a re-render.

I understand it's tempting to try and do object manipulations when you have nested fields in your state, but given that your fields are changing basically all-at-once, we can do it atomically and improve your time-to-first-meaningful-data.

As an aside, I think initialState might not be a good idea for the name of your variable. Let's call it dayInfo because that's what it is. We also need to represent the state of the app while the data is being loaded - you'll be able to show a loading UI, you can get rid of that empty useEffect() dependency-array (and the ESLint disable comment) and it also really helps debugging.

Without any further ado, here's a working version:

// Document the shape of our state:
const initialState = {
  yesterday: {},
  today: {},
  tomorrow: {}
};

// Helper function that just gets a single day (to avoid repetition)
const fetchDay = async (day) => {
  try {
    const response = await axios.post(
      `https://aztro.sameerkumar.website/?sign=aries&day=${day}`
    );
    return response.data;
  } catch (error) {
    console.error(error);
  }
};

export default function App() {
  const [loadingState, setLoadingState] = useState("NOT_LOADED");
  const [dayInfo, setDayInfo] = useState(initialState);

  useEffect(() => {
    // Only go fetch the data if we haven't tried to yet
    if (loadingState === "NOT_LOADED") {
      setLoadingState("IN_PROGRESS");
      getDayInfos();
    }
  }, [loadingState]);

  async function getDayInfos() {
    // Fire off the three requests concurrently ...
    const yesterdayPromise = fetchDay("yesterday");
    const todayPromise = fetchDay("today");
    const tomorrowPromise = fetchDay("tomorrow");

    // ... but wait for them all to resolve here
    const [yesterday, today, tomorrow] = await Promise.all([
      yesterdayPromise,
      todayPromise,
      tomorrowPromise
    ]);

    setDayInfo({ yesterday, today, tomorrow });
    setLoadingState("LOADED");
  }

  ...
}

We've now clarified exactly when we're going to go and fetch the data.

We are also using Promises more effectively, firing off the three Axios fetches concurrently, rather than one-by-one. Finally, we atomically set the state of dayInfo and also indicate that we've got the data, to avoid fetching it ever again - much safer than an empty dependency array.

仙气飘飘 2025-01-25 04:05:47

向@millhouse回答,我只补充说,在React或Redux中,保持数据尽可能贴切始终是一个好主意,因为您需要在数据上进行所有不变的操作以触发重新订阅者,并且如果您不够小心并且具有深嵌套对象,您可能会发现具有带有旧引用的嵌套对象的新对象,这些对象会导致各种微妙的行为。
如果您被迫使用深嵌套的数据结构,请尝试浸入其中,这是一个很棒的库,它使您可以直接与完全不可变的操作的结果直接突变对象深嵌套属性。

To @millhouse answer, I just add that it's always a good idea in React, or Redux, to keep your data as flatter as possible, since you need to make all immutable operations on your data to trigger the re-renders, and if you are not careful enough and have deep nested objects, you might find to have new objects with old referenced nested objects that cause all sort of subtle behaviours.
If you are forced to use deep nested data structures, try Immer which is a great library that lets you to mutate an object deep nested property directly with the same result of a fully immutable operation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文