후크에 대해 이야기해 봅시다 - 2부(useLayoutEffect 및 useMemo)

살람과 안녕하세요, 여러분!

React Hook 시리즈를 계속하면서, 이제 useLayoutEffectuseMemo 이라는 또 다른 2개의 Hook에 대해 이야기할 것입니다. 주제로 이동합니다!

하지만 그 전에 이 두 가지는 특정 사용 사례가 있을 때만 사용할 수 있는 희귀한 고리라는 점을 언급하고 싶습니다(아직 만나지 않았지만). 하지만 걱정하지 마세요. 기존 프로젝트에서 이 후크를 발견하고 이 두 후크가 어떻게 작동하는지 이해하고 싶을 수도 있습니다. 글쎄, 나는 당신을 덮었습니다!

시작할까요?

이 문서에서 다루는 주제는 다음과 같습니다.
  • useLayoutEffect - Yet another lifecycle hook!
  • The difference between useEffect and useLayoutEffect , and why it matters
  • useMemo - The memoization hook
  • When to not use useMemo
  • Conclusion



  • useLayoutEffect - 또 ​​다른 라이프사이클 후크!

    In the previous article in this series, I explained how useEffect is one of the most used hook works. To simply put it a way to understand, it covers componentDidMount and componentWillUnmount . Well, useLayoutEffect does a lot of the same thing as useEffect , and in fact, the way you write useLayoutEffect is the same!

    useLayoutEffect(() => {
      // do your `componentDidMount` thing here
      return () => {
        // do your `componentWillUnmount` here
      };
    }, [<all_dependencies_here>]);
    
    useEffect(() => {
      // do your `componentDidMount` here
      return () => {
        // your `componentWillUnmount` here
      };
    }, [<all_dependencies_here>]);
    

    Welp, two hooks with quite similar names, with the same way to write them. What is the catch?

    useEffect와 useLayoutEffect의 차이점과 중요한 이유

    However, what difference does it make compared to useEffect then?

    Well, need to know a key difference of "when" both of these hooks run. useEffect will run right after if there are any changes to any of the given dependencies to the hook, while useLayoutEffect will run after each change to the "layout", which means if there is a change to the DOM (DOM mutations). This includes if the change involves ref as well.

    Not to be mistaken, you indeed supply the same array of dependencies to useLayoutEffect as you supplied to useEffect , but it will run after the DOM change, and if any of the dependency changes. Unlike useEffect which will run right after one of the dependencies changes.

    So, when to use useEffect and when to use useLayoutEffect ? Well, since useEffect is triggered as the dependencies change, useEffect is the hook you will use most of the time. useEffect is DOM independent, which means that DOM doesn't affect the behaviour of useEffect . Simply, useEffect is to monitor state changes.

    useLayoutEffect triggers when there is a DOM mutation, so you can utilise that if you need to do some DOM-related activities, such as measuring performance, or detect DOM changes such as scroll position.


    useMemo - 메모이제이션 후크

    The fourth hook in this series is useMemo . This is for memoization. So what is memoization?

    In programming, memoization is an optimization technique that makes applications more efficient and hence faster. It does this by storing computation results in a cache and retrieving that same information from the cache the next time it's needed instead of computing it again. - Germán Cocca, freeCodeCamp

    Memoization is an optimization technique, so your app becomes faster by utilising caches. Just imagine, you are calculating the value of infinity, so you don't want to run it every time the component rerenders, right?

    const [x, setX] = useState(0);
    const valueOfInfinity = () => calculationOfInfinity(x);
    

    Just imagine, this function will run EVERY TIME component rerenders 🥶

    But first, let's see how useMemo is written, shall we?

    useMemo(() => {}, [array_of_deps]);
    
    // example
    const valueOfInfinity = useMemo(() => calculationOfInfinity(x), [x]);
    

    The first part of the useMemo hook is the function you want to run. It could be an expensive function or something you want to keep a cache of the dependency. The expensive function here means that this requires a lot of resources to run the function.

    The second part of the hook is the array of dependencies. And yes, it behaves similar to useEffect , where it will only run the function when one of the dependency change value.

    Let's say we consider the example above. Just imagine the formula to calculate infinity is extremely complex, and it will surely consume a lot of resources each time the function runs, right? And adding to that, it depends on x , which possibly changes, since it is a state.

    When you trigger useState , it will trigger the rerenders. When that happens, the function will run each time, even though the state value is unchanged. You could even trigger the useState to value "3" even though the value is already "3". But since setState is triggered, the component will rerender anyway.

    We don't want that to happen. If the value of dependency is unchanged, we want to keep it that way and not trigger the function. So useMemo will hold the value of dependency and will observe the changes, so if the value is the same as the previous value, it won't run the function. So, even though we set x to 3, even though x is already equal to 3, the function won't run. Neat, right?

    This can also be used to avoid children's rerenders too. Example:

    const TheButton = useMemo(() => <button>This button</button>, []);
    
    // In your return
    return () => (
      <TheButton />
    );
    

    In this example above, since you didn't add any dependency to the <button> component, it will only run once. Even though your parent component rerenders, <TheButton> won't rerender, since it will be the same throughout the component lifecycle. But of course, a simple component like the above example is too simple, and note that the component should be a pure component.

    useMemo를 사용하지 않는 경우

    Well, you just feel like "Hey, that means I can optimise everything by sprinkling useMemo everywhere in my code, right?

    Chotto matte! If you have this thought, you need to rethink your decision. Most of the time, useMemo make your app less optimised than you think!

    const [x, setX] = useState(0);
    const [y, setY] = useState(1);
    const theSum = useMemo(() => x + y, [x, y]);
    

    Even if you can calculate x plus y using your fingers, why do you think your app needs to monitor changes for x and y, for the sake of adding x to y?

    Most of the time, huge calculations are done by the backend, and the frontend will only retrieve the value from the API, and display it to the user.

    So, to what level of complexity do you need to use useMemo ? The answer is, it is so rare unless you need to calculate the value of infinity during rerenders. Personally, I didn't use useMemo , except for once, which is to calculate the effective interest rate of a loan based on several variables. Since that is a frontend-only app, so I had to use it. If you ask me, I do feel that the calculation might not need useMemo in the first place.

    In case you are wondering how to calculate effective interest rate .


    결론

    That's it about useLayoutEffect and useMemo . Though they are hooks provided by React, the use case for them is not as easy as you think, thus the usage of these hooks is quite rare. At least, you know how to write them and how they work, so when you need to use these hooks by encountering the use case, you already know how to use them.

    While useMemo is keeping the cache of its dependency for it to run the function, then what is useCallback ? Well, keep yourself posted for the next article on the React hooks!

    And as usual, take care of yourselves, and peace be upon ya!

    좋은 웹페이지 즐겨찾기