useEffect로 componentDidMount를 대체합니다.

componentDidMount 중지



"hooks로 전부 써 가고 싶다!"라고는 그다지 생각하지 않지만,
1부터 FC로 컴포넌트를 쓰기 시작하면,
나중에 「componentDidMount 있다」가 되었을 때에 귀찮은 일이 많이 있었으므로,
이 때 기억하자고 하면, 여러가지 시험해 본다.

최종 완제품
htps : // 코데씨 d보 x. 이오/에 m베d/단 k-샤페-mb1mh

가볍게 실장해 보았다(안되는 예)



codeSandBox를 이용한 것을 그대로 싣고 있으므로, 세세한 것은 큰 마음으로 스루 해 주세요.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const App = () => {
  return (
    <div className="App">
      <CountButtons initialCount={10} />
    </div>
  );
};

const CountButtons = ({ initialCount }) => {
  const [count, setCount] = useState(initialCount);
  const countUp = () => setCount(count + 1);
  const countDown = () => setCount(count - 1);
  useEffect(() => {
    console.log("useEffect");
  });
  return (
    <>
      <p>{count}</p>
      <button onClick={countUp}>↑↑increment↑↑</button>
      <button onClick={countDown}>↓↓decrement↓↓</button>
    </>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);


useEffect는 이런 느낌으로 쓰면, render할 때마다 실행되어 가는 것 같다.
버튼을 클릭한 후의 다시 렌더링에서도 발화해 버리고 있는 것이 콘솔을 보면 알 수 있다.
그래서, 이 쓰는 방법에서는 componentDidMount의 움직임은 재현할 수 없다.



수정 후



그럼, componentDidMount 처럼 하려면 어떻게 하면 좋을까.
처음 렌더링할 때만 발화시키고 싶다.

그 때는 제2 인수에 발화시키는 조건의 변수를 배열로 넣어 주면 좋을 것 같다.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const App = () => {
  return (
    <div className="App">
      <CountButtons initialCount={10} />
    </div>
  );
};

const CountButtons = ({ initialCount }) => {
  const [count, setCount] = useState(initialCount);
  const countUp = () => setCount(count + 1);
  const countDown = () => setCount(count - 1);
  useEffect(() => {
    console.log("useEffect");
  }, [initialCount]); // ここにinitialCountを入れる
  return (
    <>
      <p>{count}</p>
      <button onClick={countUp}>↑↑increment↑↑</button>
      <button onClick={countDown}>↓↓decrement↓↓</button>
    </>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

이렇게하면 무슨 일이 일어날 것인가,
초기 렌더링시 props로 전달되는 initialCount가 와서,
그 값을 보면 useEffect가 발화합니다.

그래서 2번째 이후는 initialCount의 값은 변하지 않으므로,
버튼을 클릭해도 useEffect는 발화하지 않습니다.
→componentDidMount의 완성.



업데이트 버튼을 누를 때만 useEffect가 콘솔 로그에 표시되므로,
제대로 초기 렌더링만 발화하게 되어 있다.

props가 없을 때



props가 있기 때문에 componentDidMount처럼 행동하는 것처럼 보이기 때문에,
props가 없을 때의 패턴을 생각해 본다.

useEffect 를 발화시키는 것은, 초기 렌더링에만 정의되고 있는 것을 제 2 인수에 넣으면 되므로,
setCount를 넣어 시도해 보자.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const App = () => {
  return (
    <div className="App">
      <CountButtons />
    </div>
  );
};

const CountButtons = () => { // propsを消す
  const [count, setCount] = useState(10);
  const countUp = () => setCount(count + 1);
  const countDown = () => setCount(count - 1);
  useEffect(() => {
    console.log("useEffect");
  }, [setCount]); // useStateで定義した関数を入れてみる
  return (
    <>
      <p>{count}</p>
      <button onClick={countUp}>↑↑increment↑↑</button>
      <button onClick={countDown}>↓↓decrement↓↓</button>
    </>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

이런 느낌으로 해 두면 좋다고 생각 실행.



할 수 있었다.
알겠습니다.

주의점



여러 사이트에서이 useEffect에 대해 조사했지만,
제2 인수에 빈 배열 [] 를 넣어도 움직이는 것 같지만, 안티 패턴인 것 같다.
잘 모르겠지만, 인적 실수를 일으키기 쉬워진다든가.

componentDidMount로 좋습니까?



useEffect로 componentDidMount의 동작을 할 수 있도록 구현해 보았지만,
useEffect 자체가 많은 처리를 할 수 있으므로,
어떤 처리가 이루어지고 있는지를 잘 보지 않으면 수정하는 것이 힘들 것 같다.

그야말로 버그의 원인이 아닐지도 모른다.

실제로 사용하고, 이것을 사용하지 않는 것이 더 좋을 때
또한 기사에서도 합시다. . .

추가



랩하면 componentDidMount라든지는 간단하게 판별할 수 있게 되는 것을 깨달았다. . .
import { useEffect } from 'react';

export const useDidMount = (func: Function) => useEffect(() => { func() }, []);
export const useWillUnMount = (func: Function) => useEffect(() => func, []);

좋은 웹페이지 즐겨찾기