[英]Triggering multiple mutations from parent component with react-query
I'm working on a project using react-query where I'm displaying a list.我正在使用 react-query 开发一个项目,我正在其中显示一个列表。 Each entry in the list consists of multiple input fields and it should be able to save just a single entry as well as possible to save all the entries at once.
列表中的每个条目都由多个输入字段组成,它应该能够只保存一个条目,也应该尽可能一次保存所有条目。
While saving the data I want to display loading indicators for the elements that are being saved a retry button in case the saving fails and a success message when it works.在保存数据时,我想为正在保存的元素显示一个加载指示器,以防保存失败,并在保存成功时显示一条成功消息。
I see it's possible to get ahold of the MutationCache , but I can't seem to find anything about triggering mutations from outside the component where it's used.我看到有可能获得MutationCache ,但我似乎找不到任何关于从使用它的组件外部触发突变的信息。
I made a small codesandbox to illustrate the setup, otherwise my code is pasted below.我制作了一个小的codesandbox来说明设置,否则我的代码粘贴在下面。 https://codesandbox.io/s/react-query-forked-5cuxgb?file=/src/Form.jsx
https://codesandbox.io/s/react-query-forked-5cuxgb?file=/src/Form.jsx
Form.js表单.js
import * as React from "react";
import { Person } from "./Person";
export const Form = () => {
const people = [
{
id: 1,
name: "John Doe",
age: 37
},
{
id: 2,
name: "Jack Johnson",
age: 45
},
{
id: 3,
name: "Jimmie Jones",
age: 23
}
];
const saveAll = () => {
// Trigger mutations here?
};
return (
<div>
{people.map((person) => (
<Person key={person.id} {...person} />
))}
<hr />
<button onClick={saveAll}>Save all</button>
</div>
);
};
Person.js Person.js
import * as React from "react";
import { useCreatePersonMutation } from "./useCreatePersonMutation";
export const Person = (props) => {
const { mutate, status } = useCreatePersonMutation(props.id);
return (
<div>
{status === "loading" && <span>Saving...</span>}
{status === "success" && <span>Success</span>}
{status === "error" && (
<button onClick={mutate} style={{ marginRight: 12 }}>
Retry
</button>
)}
{status === "idle" && (
<button onClick={mutate} style={{ marginRight: 12 }}>
Create Person
</button>
)}
<input value={props.name} disabled={status === "loading"} />
<input value={props.age} disabled={status === "loading"} />
</div>
);
};
useCreatePersonMutation使用CreatePersonMutation
import { useMutation } from "react-query";
export const useCreatePersonMutation = (id) => {
return useMutation({
mutationKey: ["Create_Person", id],
mutationFn: () => new Promise((resolve) => setTimeout(resolve, 3000))
});
};
You can't really go into the mutation cache ( queryClient.getMutationCache()
) and look for existing mutations and invoke them, because mutations only "exist" once they have been invoked with .mutate
or .mutateAsync
.您不能真正将 go 放入突变缓存 (
queryClient.getMutationCache()
) 并查找现有突变并调用它们,因为突变只有在使用.mutate
或.mutateAsync
调用后才“存在”。
So the mutations in your component aren't really "there yet".所以你的组件中的突变并不是真的“在那里”。
The easiest solution would imo be to:最简单的解决方案是:
Form
componentForm
组件中有一个单独的突变I ended up achieving the desired behaviour by executing a mutation for each person being saved.我最终通过为每个被拯救的人执行突变来实现所需的行为。
const saveAll = () => {
Promise.allSettled(people.map((person) => mutateAsync(person)));
};
In the Person
component that renders each row, I listen to the mutation cache and try to find the matching mutation by comparing the persons name with the name being passed to the mutation.在呈现每一行的
Person
组件中,我监听突变缓存并尝试通过将人员姓名与传递给突变的姓名进行比较来找到匹配的突变。
React.useEffect(() => {
queryClient.getMutationCache().subscribe((listener) => {
if (!listener) return;
if (listener.options?.variables.name !== name) return;
setStatus(listener.state.status);
});
}, [queryClient, name]);
This allows each Person
component to show the status of the mutation.这允许每个
Person
组件显示突变的状态。 And retrying a mutation is as simple as executing the mutation.重试突变与执行突变一样简单。
const retry = () => {
const mutation = queryClient.getMutationCache().find({
predicate: (mutation) => mutation.options.variables.name === name
});
if (mutation) {
mutation.execute();
}
};
It doesn't scale well performance wise if you work with large lists, since each Person
component gets notified about each and every mutation that gets triggered.如果您使用大型列表,它不会很好地扩展性能,因为每个
Person
组件都会收到有关触发的每个突变的通知。 However the lists I work with are of limited size, so for now it seems to suit my needs.然而,我使用的列表的大小有限,所以现在它似乎适合我的需要。
https://codesandbox.io/s/react-query-forked-5cuxgb https://codesandbox.io/s/react-query-forked-5cuxgb
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.