如何使用 useQuery 钩子在其他钩子中填充状态?
Posted
技术标签:
【中文标题】如何使用 useQuery 钩子在其他钩子中填充状态?【英文标题】:How can I use the useQuery hook to populate state in other hooks? 【发布时间】:2019-08-23 14:58:11 【问题描述】:我最近一直在处理一些与钩子相关的问题,因为我一直在将钩子实现到我的项目中。我不断收到错误消息“渲染的钩子比上一次渲染时更多。”
似乎我可以让我的代码工作的唯一方法是将 useQuery 钩子放在所有其他钩子之后。然而这是一个问题,因为我想用查询数据中的值填充一些状态值。
// code that doesn't error, but am not able to initialize state with query values
const [url, setUrl] = useState('')
const updateLink = useMutation(LINK_UPDATE_MUTATION,
variables:
id: props.id,
url
)
const data, loading, error = useQuery(LINK_QUERY,
variables:
id: props.id
)
if (loading)
return <div>Loading...</div>
if (error)
return <div>Error! error.message</div>
对
// code that errors with 'Rendered more hooks than during the previous render.'
const data, loading, error = useQuery(LINK_QUERY,
variables:
id: props.id
)
if (loading)
return <div>Loading...</div>
if (error)
return <div>Error! error.message</div>
const updateLink = useMutation(LINK_UPDATE_MUTATION,
variables:
id: props.id,
url
)
const [url, setUrl] = useState(data.link.url)
我希望 useQuery 钩子可以用于使用其查询数据初始化其他值。
如果这还不够代码或需要更多解释,请告诉我。谢谢。
【问题讨论】:
【参考方案1】:您需要做的是在第一个钩子产生响应时更新状态。为此,您可以使用useEffect
钩子。您需要在功能组件的顶部渲染所有钩子。
const [url, setUrl] = useState('')
const updateLink = useMutation(LINK_UPDATE_MUTATION,
variables:
id: props.id,
url
)
const data, loading, error = useQuery(LINK_QUERY,
variables:
id: props.id
)
useEffect(() =>
if(data && data.link)
setUrl(data.link.url);
, [data])
if (loading)
return <div>Loading...</div>
if (error)
return <div>Error! error.message</div>
【讨论】:
感谢您的回复。添加 useEffect 挂钩后,我现在收到错误“无法读取未定义的属性 'url'”。我相信这个错误表明数据库中的数据之前没有回来 -->useEffect(() => setUrl(data.link.url) , [data.link.url])
我应该如何延迟 useEffect 挂钩,直到数据从数据库中返回? if (loading)
负责这一点,但如果我将 useEffect 钩子移到下面,我会继续收到与以前相同的错误。
useEffect 也在初始渲染上运行。此外,您必须将 data
作为键而不是 data.link.url
传递给 useEffect 依赖数组,然后检查效果中的数据值。我更新了答案以反映变化
@ShubhamKhatri 当data
是数组或对象时会发生什么?由于依赖数组只进行浅层比较,因此 useEffect 将在组件重新呈现时被调用,因为引用的值发生变化
@Luminusss,在这种情况下,您需要确保数据引用仅在更新其状态时才会更改,因为在上述情况下,useQuery 不会在每次运行时都返回新引用,它会无缝地工作【参考方案2】:
你可以简单地按照这个方法,我也是这样做的。
const client = useApolloClient();
const [newData, setNewData] = useState(null);
const [loading, setLoading] = useState(false);
async function runQuery()
setLoading(true);
const useQueryData = await client.query(
query: SUBMITTED_ASSIGNMENTS, variables:
userId
);
setNewData(useQueryData?.data?.assignments);
console.log('newData', newData);
setLoading(false);
useEffect(() =>
runQuery();
, [newData]);
【讨论】:
OP 的 useQuery 钩子有问题,这个答案甚至没有使用。以上是关于如何使用 useQuery 钩子在其他钩子中填充状态?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 react/apollo 中调用条件 useQuery 钩子
如何将 React 钩子(useContext、useEffect)与 Apollo 反应钩子(useQuery)结合起来
如何使用 Apollo 客户端 useQuery 钩子防止不必要的重新获取?
在@apollo/react-hooks 的 useQuery 钩子中忽略了跳过参数