Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
438 views
in Technique[技术] by (71.8m points)

reactjs - Using date from React query to filter existing state causing too many re-renders

I'm using react query to call an api to retreive a list of schedule dates for users to use to update a list of selected dates from a calendar. However I'm not sure how to do this using react query. Currently the naked setDates is causing too many rerenders because it's not inside eg a useEffect() hook that I would normally use for an api call. Now I'm using react query I'm not sure where to put it?

const SomeDateComponent = ({  }) => {

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

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

  return (....)

custom Hook:

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,
    },
  );
}
question from:https://stackoverflow.com/questions/66068466/using-date-from-react-query-to-filter-existing-state-causing-too-many-re-renders

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You definitely cannot / should not call a setter function of useState during render, as this violates a core principle of React that render functions should be pure. What you can do is:

  • set it in a useEffect
const { data: existingSchedules } = useExistingScheduleDates(...)

useEffect(() => {
    setDates(...)
}, [existingSchedules])
  • set it in the onSuccess callback of useQuery
const { data: existingSchedules } = useQuery(
  'key',
  queryFn,
  {
    onSuccess: data => setDates(...)
  }
)

Both of these should work, but the question remains: Why would you need to do that? react-query is a state manager per se, so there is really no need to store that additionally in client state. The best way to use react-query is to keep the client state and the server state separated. I would suggest to store the user selection (selectedDates) in useState, have the server data handled completely by react-query (existingSchedules), and combine them in the render function if you need to:

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

const someComputedThing = computeSomeThing(existingSchedules, selectedDates)

sorry for the bad naming, I have no idea how existingSchedules works together with selectedDates, but I hope you get the idea :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...