https://s3-us-west-2.amazonaws.com/secure.notion-static.com/3a2e2775-a91c-43b1-ad52-38150a21378a/Frame_1.png

Introduction

This isn't going to be just another hooks and context tutorial, this is going to be me writing about how to do react hooks and state management like a pro. And, it can be a little too much to digest, so grab your favourite snack and jump in.

<aside> 🚨 Hold on, if you don't know the basics of react hooks and react context API, I highly recommend learning about them first.

</aside>

1. Setting the stage with hooks

So, we've been using react's new functional components and hooks for a while now, but how many of you have realized the actual power of hooks?

First, we will look at some places where a custom hook might be good and how we implement one.

1.1 A basic useDarkMode hook

So we're coders we love dark themes, but not everyone does, so we need to have some theme state in our app. We will use the window.matchMedia to match a CSS media query which is prefers-color-scheme: dark. This will tell us if the user's system theme is dark or not, and this will be our initial state.

const matchDark = '(prefers-color-scheme: dark)'

const useDarkMode = () => {
  const [isDark, setIsDark] = useState(() => {
    if (process.browser) {
      return window.matchMedia && window.matchMedia(matchDark).matches
    }
    return false
  })

  return isDark
}

export default useDarkMode

1.2 Making useDarkMode actually useful

Now some people man… they just can't decide if they want light or dark theme, so they put it on auto. And now, we have to account for THAT in our applications. How we do that is, we can attach a listener to window.matchMedia and listen for when it changes. Now to do that in code…

const matchDark = '(prefers-color-scheme: dark)'

const useDarkMode = () => {
  const [isDark, setIsDark] = useState(() => {
    if (process.browser) {
      return window.matchMedia && window.matchMedia(matchDark).matches
    }
    return false
  })

  useEffect(() => {
    const matcher = window.matchMedia(matchDark)
    const onChange = ({ matches }: MediaQueryListEvent) => setIsDark(matches)
    matcher.addListener(onChange)
    return () => {
      matcher.removeListener(onChange)
    }
  }, [setIsDark])

  return isDark
}

export default useDarkMode

And now how will be using this hook will look something like

import useDarkMode from "@hooks/useDarkMode";

const App = () => {
    const theme = useDarkMode() ? themes.dark : themes.light;

    return (
        <ThemeProvider value={theme}>
            ...
        </ThemeProvider>
    )
}

Now pat yourself on the back! You've made a useful custom hook.

1.3 The hook most needed useInView

One more common thing we often need is some way to detect if an element is in view or not. Here, most of us would find ourselves reaching for a library to do this but this is way simpler than it seems.

How to do this is simple: