gpt4 book ai didi

javascript - 如何将初始状态设置为使用 useQuery 获取的数据?

转载 作者:行者123 更新时间:2023-12-05 03:46:24 26 4
gpt4 key购买 nike

我正在使用 React 和 Apollo,我正在尝试使用 useQuery Hook 获取的数据来初始化状态,但在加载页面时出现“无法读取未定义的属性‘map’”。

const { loading, error, data } = useQuery(FETCH_BLOGS);
const [state, setState] = useState(undefined);

useEffect(() => {
if (loading === false && data) {
setState(data.blogs);
}
}, [loading, data]);

if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;

在 JSX 中,我正在调用 {renderBlogs(state)},它映射到数组上并且是抛出错误的地方。如果我传入初始数据 {renderBlogs(data.blogs)} 它可以工作,但我需要将数据存储在状态中,因为它会发生变化。

当我 console.log(state) 它记录 2 行:

  • 第一个是undefined
  • 第二个是博客数组(如屏幕截图所示)。

screenshot console log

在将状态设置为查询数据之前,页面似乎正在尝试呈现初始状态 (undefined)。是这样吗?我认为使用 useEffect 可以解决这个问题,但事实并非如此。感谢您提供任何帮助,谢谢。

最佳答案

引用 useEffect 文档:

The function passed to useEffect will run after the render is committed to the screen. Think of effects as an escape hatch from React’s purely functional world into the imperative world.

问题是 useEffect将在渲染之后 触发。这将导致以下事件链。假设 loading刚刚设置为 false并且在获取数据时没有错误。

当组件现在被渲染时 if (loading)if (error) guard 子句将被跳过,因为数据已成功加载。然而state尚未更新,因为 useEffect回调将在当前渲染后触发。此时当你调用renderBlogs(state) state仍将是 undefined .这将引发您描述的错误。

我可能遗漏了一些上下文,但从问题中显示的内容来看,没有理由使用 useEffect .而是使用 data直接。

Apollo 为 useQuery 提供的示例提供了一个很好的起点:

import { gql, useQuery } from '@apollo/client';

const GET_GREETING = gql`
query GetGreeting($language: String!) {
greeting(language: $language) {
message
}
}
`;

function Hello() {
const { loading, error, data } = useQuery(GET_GREETING, {
variables: { language: 'english' },
});
if (loading) return <p>Loading ...</p>;
return <h1>Hello {data.greeting.message}!</h1>;
}

将示例应用到您的场景中,它可能看起来非常相似。

const { loading, error, data } = useQuery(FETCH_BLOGS);

if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;

return renderBlogs(data.blogs);

如果您需要 setter,您可能需要为问题提供更多背景信息。但是,如果您想应用某种过滤器,则可能有一个 setter 的常见原因。一个简单的解决方案是计算博客状态。

const filteredBlogs = data.blogs.filter(blog => blog.title.includes(search));

在这里search将是某些状态 <input value={search} onChange={handleSearchChange} />元素。为了提高性能,您还可以选择使用 useMemo 在这里。

const filteredBlogs = useMemo(() => (
data.blogs.filter(blog => blog.title.includes(search))
), [data.blogs, search]);

如果你真的需要使用useState出于某种原因,您可以尝试 onCompleted useQuery 的选项而不是 useEffect .

const [blogs, setBlogs] = useState();
const { loading, error } = useQuery(FETCH_BLOGS, {
onCompleted: data => setBlogs(data.blogs),
});

关于javascript - 如何将初始状态设置为使用 useQuery 获取的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65308817/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com