Today I Learned

React Redux code-smells: Storing props in state

With only a few exceptions storing props in state is anti-pattern, because:

  • storing the same/similar data is not optimal usage of memory
  • keeping two sources of data in sync is brittle and bug prone
  • often there is a cleaner way of implement the feature

bad case: keeping transformed data

export function MyComponent({ dateString }) {
  // DON'T
  const [timestamp, setTimestamp] = useState(() => new Date(dateString).getTime());

  return <div>Some UI do not mind me</div>;
}

if timestamp is not changed by MyComponent, it could be implemented simply by useMemo

export function MyComponent({ dateString }) {
  // DO
  const timestamp = useMemo(() => new Date(dateString).getTime(), [dateString])

  return <div>Some UI do not mind me</div>;
}

if timestamp is changed by MyComponent, maybe parent component should handle it

export function MyComponent({ timestamp, setTimestamp }) {
  return <div>Some UI do not mind me</div>;
}

That way we’ll not have duplication of data

good case: props provide only initial/defaultValue and we do not care if it is updated

If we receive defaults from parent, then they can be safely used by the children in state. That way we could also implement state reset.

export function MyComponent({ defaultTimestamp }) {
  // OK
  const [timestamp, setTimestamp] = useState(() => defaultTimestamp);
  const resetTimestamp = () => setTimestamp(defaultTimestamp)

  return <div>Some UI do not mind me</div>;
}