改变使用 useQuery 获取的远程数据的最佳方法是什么
What is the best way to mutate remote data fetched with useQuery
我对 graphQL 和 Apollo 还很陌生。希望我能说清楚:
我正在使用 apollo/react-hook useQuery
获取数据。之后,我用数据填充一个表单,以便客户可以更改它。当他完成后,数据会使用 useMutation
.
发送回服务器
到目前为止,我使用 onCompleted
将获取的数据存储在组件状态中。看起来像这样:
import React, { useState } from 'react';
import { TextField } from '@material-ui/core';
const Index = () => {
const [state, setState] = useState(null)
const {data, loading, error} = useQuery<typeof queryType>(query, {
onCompleted: data => {
// modify data slightly
setState(data)
}
})
return (
<TextField value={state} onChange={() => setState(event.target.value)}/>
)
}
表单使用存储在组件状态中的值,表单处理程序使用 setState
更改它。
我现在的问题是,这是否是最佳实践,以及是否有必要将获取的数据存储在本地组件状态中。
似乎 useQuery
只有 responseId
的状态:https://github.com/trojanowski/react-apollo-hooks/blob/master/src/useQuery.ts
但是您也从 useQuery
中获得了一个 refetch
函数。
const { loading, error, data, refetch } = useQuery(...);
在使用 useMutation()
更新数据后,尝试调用 refetch()
。它不应该触发重新渲染。出于这个原因,您可能必须设置自己的状态。
也许是这样的:
const handleUpdate = () =>{
setData(refetch());
}
或者你在使用 useMutation
之后得到的数据也处于状态:https://github.com/trojanowski/react-apollo-hooks/blob/master/src/useMutation.ts
const [update, { data }] = useMutation(UPDATE_DATA);
data
将始终是最新值,因此您也可以这样做:
useEffect(()=>{
setData(data);
// OR
// setData(refetch());
}, [data])
因为您不想只获取和呈现数据——您希望能够在表单值更改时改变它——我们不能只按原样使用 data
。除非你使用 uncontrolled inputs and refs to manage your forms (which you probably shouldn't do),否则你将需要使用一些组件状态。
我认为你目前的做法基本没问题。最大的缺点是,如果查询需要一段时间(可能用户的互联网连接不稳定),则有一个 window 让他们开始填写表单,但一旦查询完成,他们的输入就会被覆盖。您必须明确禁用输入或隐藏表单,直到加载完成才能防止出现这种情况。
另一种方法是将您的组件分成两部分:
const Outer = () => {
const {data, loading, error} = useQuery(query)
if (!data) {
return null // or a loading indicator, etc.
}
return <Inner data={data}/>
}
const Inner = ({ data }) => {
const [value, setValue] = useState(data.someField)
<TextField value={value} onChange={() => setValue(event.target.value)}/>
}
通过在加载完成之前不渲染内部组件,我们确保我们传递给它的初始道具具有来自查询的数据。然后我们可以使用这些道具来初始化我们的状态。
我对 graphQL 和 Apollo 还很陌生。希望我能说清楚:
我正在使用 apollo/react-hook useQuery
获取数据。之后,我用数据填充一个表单,以便客户可以更改它。当他完成后,数据会使用 useMutation
.
到目前为止,我使用 onCompleted
将获取的数据存储在组件状态中。看起来像这样:
import React, { useState } from 'react';
import { TextField } from '@material-ui/core';
const Index = () => {
const [state, setState] = useState(null)
const {data, loading, error} = useQuery<typeof queryType>(query, {
onCompleted: data => {
// modify data slightly
setState(data)
}
})
return (
<TextField value={state} onChange={() => setState(event.target.value)}/>
)
}
表单使用存储在组件状态中的值,表单处理程序使用 setState
更改它。
我现在的问题是,这是否是最佳实践,以及是否有必要将获取的数据存储在本地组件状态中。
似乎 useQuery
只有 responseId
的状态:https://github.com/trojanowski/react-apollo-hooks/blob/master/src/useQuery.ts
但是您也从 useQuery
中获得了一个 refetch
函数。
const { loading, error, data, refetch } = useQuery(...);
在使用 useMutation()
更新数据后,尝试调用 refetch()
。它不应该触发重新渲染。出于这个原因,您可能必须设置自己的状态。
也许是这样的:
const handleUpdate = () =>{
setData(refetch());
}
或者你在使用 useMutation
之后得到的数据也处于状态:https://github.com/trojanowski/react-apollo-hooks/blob/master/src/useMutation.ts
const [update, { data }] = useMutation(UPDATE_DATA);
data
将始终是最新值,因此您也可以这样做:
useEffect(()=>{
setData(data);
// OR
// setData(refetch());
}, [data])
因为您不想只获取和呈现数据——您希望能够在表单值更改时改变它——我们不能只按原样使用 data
。除非你使用 uncontrolled inputs and refs to manage your forms (which you probably shouldn't do),否则你将需要使用一些组件状态。
我认为你目前的做法基本没问题。最大的缺点是,如果查询需要一段时间(可能用户的互联网连接不稳定),则有一个 window 让他们开始填写表单,但一旦查询完成,他们的输入就会被覆盖。您必须明确禁用输入或隐藏表单,直到加载完成才能防止出现这种情况。
另一种方法是将您的组件分成两部分:
const Outer = () => {
const {data, loading, error} = useQuery(query)
if (!data) {
return null // or a loading indicator, etc.
}
return <Inner data={data}/>
}
const Inner = ({ data }) => {
const [value, setValue] = useState(data.someField)
<TextField value={value} onChange={() => setValue(event.target.value)}/>
}
通过在加载完成之前不渲染内部组件,我们确保我们传递给它的初始道具具有来自查询的数据。然后我们可以使用这些道具来初始化我们的状态。