Reactjs 使用date from React查询筛选导致过多重新渲染的现有状态

Reactjs 使用date from React查询筛选导致过多重新渲染的现有状态,reactjs,react-query,Reactjs,React Query,我使用react query调用api来检索计划日期列表,供用户用于更新日历中选定日期的列表。 但是,我不确定如何使用react查询来实现这一点。目前,裸setDates导致了太多的重新渲染,因为它不在通常用于api调用的useEffect()钩子中。现在我使用的是react查询,我不知道该放在哪里 const SomeDateComponent = ({ }) => { const [selectedDates, setSelectedDates] = React.useStat

我使用react query调用api来检索计划日期列表,供用户用于更新日历中选定日期的列表。 但是,我不确定如何使用react查询来实现这一点。目前,裸setDates导致了太多的重新渲染,因为它不在通常用于api调用的useEffect()钩子中。现在我使用的是react查询,我不知道该放在哪里

const SomeDateComponent = ({  }) => {

  const [selectedDates, setSelectedDates] = React.useState<selectedDates>({});
  .....
  
  const { data: existingSchedules } = useExistingScheduleDates(
    startDate,
    endDate,
    userIds.map((agent) => agent.userId),
  );

  
  setDates((selectedDates) => ({ ...selectedDates, ...existingSchedules }))

  return (....)
const SomeDateComponent=({})=>{
const[selectedDates,setSelectedDates]=React.useState({});
.....
const{data:existingSchedules}=useExistingScheduleDates(
开始日期,
结束日期,
userId.map((agent)=>agent.userId),
);
setDates((selectedDates)=>({…selectedDates,…existingSchedules}))
返回(…)
自定义挂钩:

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,
    },
  );
}
导出函数使用现有ScheduleDates(
开始日期:,
结束日期:日期,
userid:number[],
):QueryObserverResult{
返回useQuery(
['existingSchedules',startDate,endDate],
() => {
返回全部({
路由:'/schedulesExist',
查询:{
startDate:格式(startDate,dateFormat),
endDate:格式(endDate,dateFormat),
userId:userId,
},
});
},
{
refetchOnWindowFocus:false,
},
);
}

在渲染期间,您绝对不能/不应该调用
useState
的setter函数,因为这违反了React的核心原则,即渲染函数应该是纯函数。您可以做的是:

  • 将其设置为一个有用的效果
  • useQuery的
    onSuccess
    回调中设置它
这两种方法都应该有效,但问题仍然是:为什么需要这样做?react query本身就是一个状态管理器,因此实际上不需要将其另外存储在客户端状态。使用react query的最佳方法是将客户端状态和服务器状态分开。我建议存储用户选择(
selectedDates
)在
useState
中,通过react查询(
existingSchedules
)完全处理服务器数据,并在需要时将它们组合到渲染函数中:

const { data: existingSchedules } = useExistingScheduleDates(...)
const [selectedDates, setSelectedDates] = React.useState<selectedDates>({})

const someComputedThing = computeSomeThing(existingSchedules, selectedDates)
const{data:existingSchedules}=useExistingScheduleDates(…)
常量[selectedDates,setSelectedDates]=React.useState({})
const someComputedThing=计算某物(现有计划、选定日期)

很抱歉命名不正确,我不知道现有计划如何与选定日期一起工作,但我希望您能理解:)

谢谢您的详细回答。我没有提到someComputedThing将传递给要使用的子组件。(原始用户选择的日期将被现有计划日期过滤,这些日期是已经存在计划的日期,因此需要使用此数据更新所选日期(通过使用该状态段或创建新的状态段并传递给子组件)。因此,看起来您建议的最后一个选项可能不起作用?为什么不起作用?如果计算结果可以传递给子组件,那么您可以将结果传递给子组件。如果子组件已被记忆,并且您希望在每个渲染中传递相同的引用,而没有任何更改,则可以将计算包装在
React.useMoom
中。
const { data: existingSchedules } = useQuery(
  'key',
  queryFn,
  {
    onSuccess: data => setDates(...)
  }
)
const { data: existingSchedules } = useExistingScheduleDates(...)
const [selectedDates, setSelectedDates] = React.useState<selectedDates>({})

const someComputedThing = computeSomeThing(existingSchedules, selectedDates)