Skip to content

KynaAcademy/typescript_hooks_exercises

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React hooks exercise bank

This is just a bunch of custom hooks that you can practice on.

Each of the hooks has a test file. You can run the tests using npm run test (or yarn run test if you prefer). By default, all the tests are skipped, like so:

test.skip("some case", () => {
  // ...
});

You've solved an exercise if you've been able to make the hook work for each test case, which you can "unskip" by just removing the .skip part:

test("some case", () => {
  // ...
});

Solutions for each of the exercises can be found in the Pull Requests.

useToggle

The idea: when we're just working with a booling state cell, it's a bit of a nuisance to often have to write an extra toggle helper function. Implement this hook to satisfy the API:

const [on, toggle] = useToggle();
const [on, toggle] = useToggle(initialValue);

where

useToggle: (initialValue?: boolean) => [boolean, () => void];

useEffectOnce

This hoop should be used like so:

useEffectOnce(() => {
  console.log("hi");
});

and can also have a cleanup function, just like a normal effect:

useEffectOnce(() => {
  console.log("hi");

  return () => {
    console.log("cleaning up");
  };
});

It should be called exactly once, as an effect.

usePrevious

Sometimes you want to remember the "previous value", like in this game:

function PubQuiz() {
  const [answer, setAnswer] = useState("Belgium");
  const previousAnswer = usePrevious(answer);

  return (
    <div>
      <p>Your answer: {answer}</p>
      <p>Your previous answer: {previousAnswer}</p>
      ...
    </div>
  );
}

The hook should always return the value that the variable had in the previous render.

TODO add a "distinct" flag to save the previous value until distinctly new, not just a subsequent render.

useLatest

TODO describe

useValidated

Example usage:

const useValidated = createUseValidated((email: string) => {
  return !!email.match(EMAIL_REGEX);
});

const SignupForm = () => {
  const [email, setEmail] = useState("");
  const emailValid = useValidated(email);
  // emailValid: "idle" | "valid" | "invalid"

useAsyncCallback

Example usage:

const { call, callAsync, status, data, error } = useAsyncCallback(async () => {
  const res = await axios.get("...");
  const data = await res.json();
  return data;
});

TODO: useRememberDeep

Example usage:

const [name, setName] = useState("Gordon");

const params = useRememberDeep({
  name,
  hobbies: ["cooking", "yelling", "puns"],
});

// ^^ params has the same data as the value passed into the
//  hook, but is guaranteed to be referentially stable
//  as long as the value doesn't change structurally

TODO: useDeepCompareEffect

Exammple usage:

const [name, setName] = useState("Gordon");

const params = {
  name,
  hobbies: ["cooking", "yelling", "puns"],
};

useDeepCompareEffect(() => {
  // ...
}, [params]);

This effect should only run when it's dependencies array changes structurally. If a dependency is a different object reference but structurally the same as the previous render, don't run the effect.

(Should also support cleanup, just like regular effects.)

TODO: useStateWithHistory

Example usage in a game of tic-tac-toe:

const [board, setBoard, { undo, redo, history, index }] = useStateWithHistory([
  ["X", " ", "O"],
  ["O", " ", " "],
  [" ", " ", " "],
]);

The history behaves like browser history, which means that:

  • if you "undo", you go back in history (if possible), but the history is kept in memory
  • if you "redo", you go forward in history (if possible)
  • if you set a new value, and there's "future history" which you've undone, then that future history is replaced with the new value

Hint: use a single useState (or a single useReducer), instead of multiple state cells and/or useRef. You can also make it with refs or multiplle state cells, but it will be easier to think about it with just a single state cell.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published