kevin
kevin

Reputation: 3528

Redux createSelector doesn't appear to memoize results

I've been reading the docs on createSelector and i'm under the impression that it's supposed to memoize the results to avoid expensive calculations. However, for some reason my console.logs are firing in functions that should'nt be firing. Curious why that is, am I doing something wrong? By the time I reach this specific component, the data already exists in the store in the same shape so it should be memoized.

in my component:

  const dispatch = useAppDispatch();
  const rawTranscript = useAppSelector(selectRawTranscript);
  const parsedTranscript = useAppSelector(selectParsedTranscript);

  const parsedResult = useMemo(() => {
    // rawTranscript should be memoized ... 
    return transcriptParser(rawTranscript, undefined, 0.9);
  }, [rawTranscript]);

  useEffect(() => {
    // this also fires, I initially had the parsed result here but the same behavior happened.
    // const parsedResult = transcriptParser(rawTranscript, undefined, 0.9);
    dispatch(updateParsedTranscript(parsedResult));
  }, [dispatch, parsedResult]);

in my redux slice:

// selectRawTranscript should be memoized (createSelector is used)
export const selectRawTranscript = createSelector(
  (state: RootState) => state.transcript.rawTranscript,
  rawTranscript => rawTranscript
);

export const selectParsedTranscript = createSelector(
  (state: RootState) => state.transcript.parsedTranscript,
  parsedTranscript => parsedTranscript
);

Upvotes: 0

Views: 1175

Answers (1)

markerikson
markerikson

Reputation: 67627

Your selectors really aren't "memoizing" anything. Any time you have a use of createSelector where the output selector is just x => x, there's no real memoization happening. This is exactly equivalent to a plain function that is just state => state.x - you're just returning the field as-is.

Based on the code you've shown so far, the component will re-render any time the state.transcript.rawTranscript or state.transcript.parsedTranscript fields are updated by the reducer, and the effect will re-run every time the state.transcript.rawTranscript field is updated.

I'd suggest reading through the recently updated Redux docs page on selectors to get a better idea of when, how, and why to write memoized selector functions.

Also, having the effect depend on the parsed transcript, and then also dispatch an action that looks like it's saving the parsed value, seems a bit odd and with potential to cause extra re-renders.

Beyond that

Upvotes: 3

Related Questions