Home > database >  Deriving state from a useStates instead of store
Deriving state from a useStates instead of store

Time:08-31

Afternoon fine people of the internet.

I'm building a little react component that will be standalone. ie. not part of a larger app with a redux store.

I'm using a few useStates to hold some states, and I'd like to derive some additional data from those states.

export function useNeatoThing() {
  const [datasetA, setDtasetA] = useState();
  const [datasetB, setDtasetB] = useState();

  fetch("apiA") ~~ pseudocode ~~> setDtasetA(data)
  fetch("apiB") ~~ pseudocode ~~> setDtasetB(data)

  const [myDerivedThing, setMyDerivedThing] = useState<number | undefined >()
  
  return {myDerivedThing, data: {datasetA, datasetB}}
}

I'm wondering what the best pattern is.

I would very much like to avoid using a useEffect to do the derivation. This just feels clunky:

useEffect(() => {
  if (datasetA && datasetB) {
    setMyDerivedThing(datasetA.alpha * datasetB.gamma)
  }    
}, [datasetA, datasetB] )

Am I stressing over nothing or is there a better way to do this?

CodePudding user response:

You should not be using useEffect to set a derived state. You shouldn't be having a state that is derived from state or props in the first place. Just calculate it on render. If it's an expensive calculation, use useMemo to memoize the operation. So your code should be

export function useNeatoThing() {
  const [datasetA, setDatasetA] = useState();
  const [datasetB, setDatasetB] = useState();

  fetch("apiA")~~~~> setDtasetA(data)
  fetch("apiB")~~~~> setDtasetB(data)

  const derivedThing = useMemo(() => {
      if (datasetA && datasetB) 
      return datasetA.alpha * datasetB.gamma;
   }, 
    [datasetA, datasetB])
  
  return {state, available, myDerivedThing, data: {datasetA, datasetB}}
}

Using useEffect for it makes it more complicated than necessary. It is inefficient too: it does an entire render pass with a stale value for the derived value, then immediately re-renders with the updated value.

As a rule, when you can derive something from state or props, you should not put it in a state.

  • Related