Search code examples
reactjstypescriptrtk-query

How to properly deal with code that need to wait for previous constants to be loaded?


Here is a change to a long code before a render that wasted me time to correct many lines in the code:

Before:

const my_model:MyModel = JSON.parse(localStorage.getItem('my_model')!)
const my_positions:MyModel = JSON.parse(localStorage.getItem('my_positions')!)

After:

const waitformyIcm:Boolean = useDetailMyModelQuery(paramid.id).isSuccess;
const myIcm:undefined | MyModel| any = useDetailMyModelQuery(paramid.id).data
const waitforpositions:Boolean = usePatternPositionsPerModelQuery(paramid.icm).isSuccess;
const positions:undefined | PatternPositions[] = usePatternPositionsPerModelQuery(paramid.icm).data

The consequence is that for almost all the next constants I needed to let the program wait until those first lines completed loading. My question is how to cope with such situations because I feel my approach was not as it should:

For example this previous line would already cause crashes:

const harvestAfter:number[] = [myIcm.length_period1, myIcm.length_period2, myIcm.length_period3]

This was solved by:

const harvestAfter:number[] = waitformyIcm && [myIcm.length_period1, myIcm.length_period2, myIcm.length_period3]

Another challenge was to set a default state with data that had to be loaded first. I solved that with:

const [myFilters, setMyFilters] = useState(myfilters);
useEffect(() => setMyFilters(myfilters), [myfilters && waitforpositions]);

How to properly deal with code that need to wait for previous constants to be loaded in REACT?

  • Using myconst && ......?
  • Using useEffect?
  • Using useRef?
  • Using async await (how to do that for declaring constants)
  • Other?

Solution

  • Please don't call the same hook multiple times, that is just a waste of user memory and CPU time. (These hooks are doing work internally and you invoke them twice for no good reason.)
    Just don't annotate the types here and assign them to a variable. They are already 100% typesafe from the hook.

    Then, use skip:

    const icmResult = useDetailMyModelQuery(paramid.id);
    const patternsResult = usePatternPositionsPerModelQuery(paramid.icm, { skip: !icmResult.isSuccess });
    

    As for the variable assignment, you could also use destructuring although I don't really see the point:

    const { isSuccess: waitformyIcm, data: myIcm } = useDetailMyModelQuery(paramid.id);
    

    As for a default state, there are many approaches. If it is an object you define inline, it would be a new reference on every render, so you best useMemo to get around that:

    const filtersWithDefaults = useMemo(() => filters ?? defaultFilters, [filters])