我们正在使用 CRA 开始一个新的 React 项目。并且,计划使用 React Query。
需要有关项目文件夹结构的帮助。基于功能的文件夹结构与基于文件类型的结构相比有何优势?
另外,仅使用 axios/fetch 调用并直接在组件中创建 useQuery/useMutation 挂钩的服务/API 有什么优势?与为每个reactQuery 创建自定义 Hook 相比?
// API call in a service file and using that API call in the component
export const fetchPost = (key, postId) =>
axios.get(`/api/posts/${postId}`).then((res) => res.data)
//Custom Hooks for each API call in a service
export default function usePost(postId) {
return useQuery(postId && ['post', postId], fetchPost)
}
Run Code Online (Sandbox Code Playgroud) 假设我有一个查询来获取电影集合:
useQuery(['movies'], getMovies)
Run Code Online (Sandbox Code Playgroud)
现在,如果我只想重新获取一部电影而不是所有电影,我可以编写如下内容:
useQuery(['movies', movieId], () => getMovie(movieId))
Run Code Online (Sandbox Code Playgroud)
问题是我使用不同的查询键并且它会重复数据。我会将这部电影放入缓存中两次。
那么,更新获取的集合中的单个项目的反应查询方式是什么?useQuery(['movies'])当获取单个项目时,所有使用的组件都应该自动更新。
我是第一次尝试 React Query,我写了这个:
export function Component(): JSX.Element {
const queryClient = new QueryClient()
const { data } = useQuery<DataType>({
queryKey: "myKey",
queryFn: () => ....,
})
const sameData: DataType| undefined = queryClient.getQueryData("myKey")
return (
<>
{console.log(data)}
{console.log(sameData)}
<p>Loaded, see console for values.</p>
</>
)
}
Run Code Online (Sandbox Code Playgroud)
数据对象是按预期创建的,但我似乎无法使 sameData 返回除未定义之外的任何内容。我知道这意味着 React Query 找不到我的密钥。有人对如何解决这个问题有任何想法吗?
我正在尝试使用 React guery 从这个函数中获取一些SATA。
export const quotaReservationRefundServiceBankAccount = (
id: string,
bankAccountInformation: IBankAccountInformation,
quotaLegal?: string,
): Promise<Response> => {
const url = `${appSettings.bffUrl}/api/pregnancies/quotareservations/${id}/bankaccount/refund`;
const body: IRefundQuotaReservationRequest = {
language: appSettings.language,
bankAccountInformation,
legalDepartmentShortCode: quotaLegal || "",
};
return post(url, body);
};
Run Code Online (Sandbox Code Playgroud)
我得到的是这个票价:
const { data: testData, isLoading, error } = useQuery<string, IBankAccountInformation, string | undefined>(["bankRefundResponse", quota?.reservation || "Quota.reservation missing", bankAccountInfo, quota.legal], quotaReservationRefundServiceBankAccount, {
});
Run Code Online (Sandbox Code Playgroud)
打字稿给了我这个错误:
类型为“(id: string,bankAccountInformation: IBankAccountInformation,quotaLegal?: string | undefined) => Promise”的参数不可分配给类型为“QueryFunction<string, QueryKey>”的参数。ts(2345)
我想保留以前的数据并在加载时在数据顶部使用微调器。
我知道 isLoading 仅在硬加载时返回 true。但是,使用 isFetching 将在有后台提取时触发微调器出现。
当keepPreviousData打开时,有什么方法可以获取加载状态吗?
我试图取消任何以前/待处理的请求,如果它们花费的时间太长并且用户导航到另一个组件,当前查询采用状态值,并且当它更改组件重新渲染时,这很好并且是所需的行为。然而,在网络选项卡中查看请求仍处于待处理状态。有没有办法在反应查询中取消任何以前的请求。我尝试根据文档取消查询,但它不正确,因为它没有取消。
const [value, setValue] = React.useState<boolean>(false);
const getData = async (value: number): Promise<any> => {
const CancelToken = axios.CancelToken
const source = CancelToken.source()
const response = await axios.get(`https://xxxxxx?value=${value}`, {
cancelToken: source.token,
}).then(res => res.data);
if (CancelToken) {
response.cancel = () => {
source.cancel('Query was cancelled by React Query')
}
}
return response;
}
const { data: result, status, error, isFetching }: any = useQuery(['getData', value], () => getData(value),
{
refetchOnWindowFocus: false,
}
);
Run Code Online (Sandbox Code Playgroud) 我最近开始使用功能组件和react-query进行react,它运行良好,只是我不清楚如何正确组织组件。
我习惯设计组件的方式是使用一个顶级组件来执行所有数据访问并通过 props 将数据传递给它的子组件。它还将各种回调处理程序传递给子组件,以便在需要操作时,顶级组件将更新数据并将新数据传递给子组件。所以在我的例子中,所有对 useQuery()、useMutation() 的调用都驻留在顶级组件中,但这使代码变得极其混乱。但它很像包含各种子组件的页面,这些子组件仅显示数据或帮助用户与数据交互。
function Page(){
const [page, setPage] = useState(1)
const [size, setSize] = useState(10)
const persons = useQuery('persons', async ()=> await getPersons(page, size))
const addPerson = useMutation(async (args)=> {
const {id, name, desc} = args
await addPerson(id, name, description)
})
const person = useQuery('persons', async ()=> await getOnePerson(page, size), { enabled : false })
const addPersonCB = (id: number, name: string, desc: string)=> {
addPerson.mutate({id, name, desc})
}
// complex if/else logic to choose child components …Run Code Online (Sandbox Code Playgroud) typescript reactjs react-hooks react-functional-component react-query
当使用useInfiniteQueryhook from时react-query,我们得到data以下对象:
https://react-query.tanstack.com/guides/infinite-queries
基本上,我们在属性内获得多个页面data.pages,这是一个页面数组。
每个页面都有一个items包含结果项数组的属性。
我需要将所有这些合并pages[i].items到一个数组中。而且我无法预先确定已获取了多少页。
对此的最佳实践/模式是什么?
这是要走的路吗?
const allItems = ([] as Array<ItemType>).concat(...data.pages.map((page) => page.items));
Run Code Online (Sandbox Code Playgroud) 我试图useMutation以尽可能最好的方式实现并保持某种干净代码的感觉,但我在如何最好地管理复杂的调用方面遇到了麻烦。
例如,当一个人在我的应用程序上创建帐户时,需要发生以下几件事:
也许最好的解决方案是尝试在后端的一次调用中完成所有这些工作,如果这是最好的方法,我愿意这样做,但这感觉就像将太多的东西混合到后端的自定义路由中。
假设我希望它们都是单独的呼叫,当用户单击注册按钮时发生,那么管理这些呼叫的最佳方法是什么?
我一直在使用onSuccessuseMutation 的回调并调用该部分链中的下一个调用,但感觉非常臃肿。再说一次,如果这是最好的方法,我很高兴,但我很想听到关于更好方法的建议。
这是我制作onSuccess版本的方法:
const doSendVerification = useMutation((email)=>sendVerification(email),
{
onSuccess: (data)=>{
storeCookie(data)
redirect('nextPath')
},
onError: (err)=>{handleError(err}
})
const doCreateUser = useMutation((user)=>createUser(user),
{
onSuccess: (data)=>{doSendVerification.mutate(data)},
onError: (err)=>{handleError(err}
})
const doVerifyRecaptcha = useMutation((token)=>verifyRecaptcha(token),
{
onSuccess: (data)=>{doCreateUser.mutate(data)},
onError: (err)=>{handleError(err}
})
Run Code Online (Sandbox Code Playgroud)
或者,我可以将它们全部放在一个函数中并使用 mutateAsync。我知道在下面的情况下,不会包含 onSuccess 回调。像这样的东西:
const handleSubmit = async ()=> {
try {
const verified = await doVerifyRecaptcha.mutateAsync(token)
const newUser = await doCreateUser.mutateAsync(userInfo)
const sendEmail = await doSendVerification.mutateAsync(emailInfo)
storeLoginCookie(newUser)
redirect('nextPath') …Run Code Online (Sandbox Code Playgroud) 在 ReactQuery 中,useQuery(..)钩子采用一个可以包含复杂依赖项(在数组中)的键。或者甚至只是一个int, 像todoId这样可以改变(参见文档)。
或者像filters下面这样的对象:
function Component() {\n const [filters, setFilters] = React.useState() \n const { data } = useQuery([\'todos\', filters], () => fetchTodos(filters))\n\n // \xe2\x9c\x85 set local state and let it "drive" the query\n return <Filters onApply={setFilters} />\n}\nRun Code Online (Sandbox Code Playgroud)\n我无法找到有关它如何监视幕后变化的解释。
\n如果源代码中很好地解释了密钥的散列,并且这篇博客文章对值更改的事件处理/监视对我来说是一个谜。
\n所以问题是:它如何跟踪更改,即使是在查询键数组中传递的复杂类型内部?是否发生了一些内省,将事件与值和/或参考变化联系起来?
\nPS:这个问题也适用于 useEffect(..) 挂钩中的依赖项。我对非解释性语言普遍感到困惑。
\n