skip to Main Content

In my React component I want to access the results of memoization inside the event handler that fetched the data that’s being memoized, like this:

const [theData, setTheData] = React.useState(null)

const memoizedData = React.useMemo(() => {
  return someComplexProcessOn(theData)
}, [theData])

const buttonClick = async () => {
  const newData = await fetchTheData()
  setTheData(newData)
  // now I want to access memoizedData
}

Obviously inside the event handler the memoization hasn’t happened yet but I need to access the memoized data in order to complete the handling of the event

The only way I can think to do this is have a useEffect, but I don’t want the processing to happen every time theData changes, only in response to this specific event, so I would have to introduce a new state variable called completeEventProcessingNow and have the effect depend on that as well

The react docs (https://react.dev/learn/you-might-not-need-an-effect) are pretty keen to point out that you shouldn’t use useEffect to do things in response to user events but I don’t see how else I can handle it in this case.

2

Answers


  1. Chosen as BEST ANSWER

    FWIW (and unless another better answer appears) I ended up calling someComplexProcessOn once in the event handler to get the values I need right away, and then again in a useMemo to memoize them for subsequent renders. my processing wasn't so disastrously slow that I couldn't afford to call it twice.


  2. I would implement recalculation of memoizedData wherever the data it depends on is being changed, so it would look like this:

    const [theData, setTheData] = React.useState(null)
    const [memoizedData, setMemoizedData] = React.useState(() => someComplexProcessOn(theData)) // note: https://react.dev/reference/react/useState#avoiding-recreating-the-initial-state
    
    const buttonClick = async () => {
      const newData = await fetchTheData()
      setTheData(newData)
    
      const newMemoizedData = someComplexProcessOn(newData)
      setMemoizedData(newMemoizedData)
      // now I want to access memoizedData
      // you can access memoizedData in this function using newMemoizedData
      // or from other part of the code using memoizedData from state
    }
    

    or if the fetched data may not change (and you don’t want to recalculate in such case) you can do:

    const [theData, setTheData] = React.useState(null)
    const [memoizedData, setMemoizedData] = React.useState(() => someComplexProcessOn(theData))
    
    const buttonClick = async () => {
      const newData = await fetchTheData()
      setTheData((oldData) => {
        if (oldData !== newData) {
          const newMemoizedData = someComplexProcessOn(newData)
          setMemoizedData(newMemoizedData)
        }
        return newData
      })
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search