jmalvarez.dev
Menu

Epic React: Advanced React Hooks

Author's avatar
José Miguel Álvarez VañóMarch 22, 2022

Exercise 1

When should I use useState?
When it's just an independent element of state you're managing.

When should I use useReducer?
When one element of your state relies on the value of another element of your state in order to update.

If multiple setStates are called in an event handler or in a useEffect, then they are batched and only one rerender is triggered.

Exercise 2

Memoization: a performance optimization technique which eliminates the need to recompute a value for a given input by storing the original computation and returning that stored value when the same input is provided.

The caching strategy React has adopted has a size of 1. That is, they only keep around the most recent value of the input and result.

React builds a tree in an object which keeps track of the hooks, that’s how React knows which hook was called and can return the correct values. Example of the tree:

{
 state: 0,
 dispatcher: ReactDispatcher.someFunction
 next: {
  {
   state: "another state",
   dispatcher: ReactDispatcher.anotherFunction
  }
 }
}

Exercise 3

React Context is used to share data that can be considered global.

In case that we want to only avoid prop drilling, usually a simpler solution is component composition. More info about this: Using Composition in React to Avoid "Prop Drilling" - YouTube

Exercise 4

When to use...

Exercise 5

forwardRef can be used to forward a reference to a DOM component which is rendered in one the children components.

const MyInput = forwardRef((props, ref) => {
  return <input ref={ref} />;
});

const App = () => {
  const ref = React.useRef();

  const focus = () => {
    ref.current.focus();
  };

  return <MyInput ref={ref} />;
};

We could also expose imperative methods:

const MyInput = forwardRef((props, ref) => {
  const inputRef = React.useRef();
  ref.current = {
    focusInput: () => inputRef.current.focus(),
  };

  return <input ref={inputRef} />;
});

const App = () => {
  const ref = React.useRef();

  const focus = () => {
    ref.current.focusInput();
  };

  return <MyInput ref={ref} />;
};

But, instead of manipulating directly the ref, React has a hook called useImperativeHandle which does this for us:

const MyInput = forwardRef((props, ref) => {
  const inputRef = React.useRef();

  useImperativeHandle(ref, () => ({
    focusInput: () => inputRef.current.focus(),
  }));

  return <input ref={inputRef} />;
});

const App = () => {
  const ref = React.useRef();

  const focus = () => {
    ref.current.focusInput();
  };

  return <MyInput ref={ref} />;
};

Exercise 6

useDebugValue makes it possible to provide extra information of a custom hook in the React Dev Tools. It only works inside custom hooks.

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  // Show a label in DevTools next to this Hook
  // e.g. "FriendStatus: Online"
  useDebugValue(isOnline ? "Online" : "Offline");

  return isOnline;
}

Resources

José Miguel Álvarez Vañó
© 2022
jmalvarez.dev