使用来自 React 查询的日期来过滤导致过多重新渲染的现有状态
Using date from React query to filter existing state causing too many re-renders
我正在使用 React 查询调用 api 来检索计划日期列表,供用户用来更新日历中的选定日期列表。
但是我不确定如何使用反应查询来做到这一点。目前,裸露的 setDates 导致了太多的重新渲染,因为它不在我通常用于 api 调用的 useEffect() 挂钩内。现在我正在使用反应查询我不知道把它放在哪里?
const SomeDateComponent = ({ }) => {
const [selectedDates, setSelectedDates] = React.useState<selectedDates>({});
.....
const { data: existingSchedules } = useExistingScheduleDates(
startDate,
endDate,
userIds.map((agent) => agent.userId),
);
setDates((selectedDates) => ({ ...selectedDates, ...existingSchedules }))
return (....)
自定义挂钩:
export function useExistingScheduleDates(
startDate: Date,
endDate: Date,
userIds: number[],
): QueryObserverResult<ExistingScheduleDates> {
return useQuery(
['existingSchedules', startDate, endDate],
() => {
return apiCall( {
route: '/schedulesExist',
query: {
startDate: format(startDate, dateFormat),
endDate: format(endDate, dateFormat),
userId: userIds,
},
});
},
{
refetchOnWindowFocus: false,
},
);
}
你绝对不能/不应该在 渲染期间调用 useState
的 setter 函数,因为这违反了 React 的核心原则,即渲染函数应该纯洁。你可以做的是:
- 在useEffect中设置
const { data: existingSchedules } = useExistingScheduleDates(...)
useEffect(() => {
setDates(...)
}, [existingSchedules])
- 在
useQuery
的onSuccess
回调中设置
const { data: existingSchedules } = useQuery(
'key',
queryFn,
{
onSuccess: data => setDates(...)
}
)
这两种方法都应该有效,但问题仍然存在:您为什么需要这样做? react-query 是 本身的状态管理器,因此实际上没有必要将其额外存储在客户端状态中。使用 react-query 的最佳方式是保持客户端状态和服务器状态分离。我建议将用户选择 (selectedDates
) 存储在 useState
中,让服务器数据完全由 react-query (existingSchedules
) 处理,并在需要时将它们组合到渲染函数中至:
const { data: existingSchedules } = useExistingScheduleDates(...)
const [selectedDates, setSelectedDates] = React.useState<selectedDates>({})
const someComputedThing = computeSomeThing(existingSchedules, selectedDates)
抱歉命名错误,我不知道 existingSchedules
如何与 selectedDates
一起工作,但我希望你能理解 :)
我正在使用 React 查询调用 api 来检索计划日期列表,供用户用来更新日历中的选定日期列表。 但是我不确定如何使用反应查询来做到这一点。目前,裸露的 setDates 导致了太多的重新渲染,因为它不在我通常用于 api 调用的 useEffect() 挂钩内。现在我正在使用反应查询我不知道把它放在哪里?
const SomeDateComponent = ({ }) => {
const [selectedDates, setSelectedDates] = React.useState<selectedDates>({});
.....
const { data: existingSchedules } = useExistingScheduleDates(
startDate,
endDate,
userIds.map((agent) => agent.userId),
);
setDates((selectedDates) => ({ ...selectedDates, ...existingSchedules }))
return (....)
自定义挂钩:
export function useExistingScheduleDates(
startDate: Date,
endDate: Date,
userIds: number[],
): QueryObserverResult<ExistingScheduleDates> {
return useQuery(
['existingSchedules', startDate, endDate],
() => {
return apiCall( {
route: '/schedulesExist',
query: {
startDate: format(startDate, dateFormat),
endDate: format(endDate, dateFormat),
userId: userIds,
},
});
},
{
refetchOnWindowFocus: false,
},
);
}
你绝对不能/不应该在 渲染期间调用 useState
的 setter 函数,因为这违反了 React 的核心原则,即渲染函数应该纯洁。你可以做的是:
- 在useEffect中设置
const { data: existingSchedules } = useExistingScheduleDates(...)
useEffect(() => {
setDates(...)
}, [existingSchedules])
- 在
useQuery
的
onSuccess
回调中设置
const { data: existingSchedules } = useQuery(
'key',
queryFn,
{
onSuccess: data => setDates(...)
}
)
这两种方法都应该有效,但问题仍然存在:您为什么需要这样做? react-query 是 本身的状态管理器,因此实际上没有必要将其额外存储在客户端状态中。使用 react-query 的最佳方式是保持客户端状态和服务器状态分离。我建议将用户选择 (selectedDates
) 存储在 useState
中,让服务器数据完全由 react-query (existingSchedules
) 处理,并在需要时将它们组合到渲染函数中至:
const { data: existingSchedules } = useExistingScheduleDates(...)
const [selectedDates, setSelectedDates] = React.useState<selectedDates>({})
const someComputedThing = computeSomeThing(existingSchedules, selectedDates)
抱歉命名错误,我不知道 existingSchedules
如何与 selectedDates
一起工作,但我希望你能理解 :)