본문 바로가기

React

[React 기초] 05. effects

아래 코드에서 state가 변경될 때마다, console.log가 실행된다.

첫 번째 render할 때만 실행하고 싶다면?

import { useState } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const onClick = () => setValue((prev) => prev + 1);
  console.log("call an API");
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

 

useEffect

  • 컴포넌트 안에 딱 한 번만 실행하고 싶은 코드가 있을 경우
  • 컴포넌트 안에 특정 데이터가 변화할 때만 실행해야하는 경우
  • dependencies: React가 지켜봐야하는 것
    • dependencies가 [] (빈 리스트)이면 지켜봐야할 것이 없다 = 한 번만 실행
import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const onClick = () => setValue((prev) => prev + 1);
  console.log("I run all the time");
  const iRunOnlyOnce = () => {
    console.log("I run only once");
  };
  useEffect(iRunOnlyOnce, []);
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

예제 - 검색창 작동 방식

import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => {
    setKeyword(event.target.value);
  };
  console.log("I run all the time");
  useEffect(() => {
    console.log("i run only once");
  }, []);
  console.log("SEARCH FOR", keyword);
  return (
    <div>
      <input
        value={keyword}
        onChange={onChange}
        type="text"
        placeholder="Search here"
      ></input>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

Problem

  • input에 있는 단어가 변경될 때마다 SEARCH FOR 실행
  • 검색과 관련 없는 button을 onClick시에도 SEARCH FOR 실행

Scratch

useEffect를 사용, 두 번째 인자에 keyword 변수 사용
useEffect(() => {
  console.log("SEARCH FOR", keyword);
}, [keyword]);
import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => {
    setKeyword(event.target.value);
  };
  console.log("I run all the time");
  useEffect(() => {
    console.log("i run only once");
  }, []);
  useEffect(() => {
    console.log("SEARCH FOR", keyword);
  }, [keyword]);
  return (
    <div>
      <input
        value={keyword}
        onChange={onChange}
        type="text"
        placeholder="Search here"
      ></input>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

Scratch 2

처음에 SEARCH FOR가 실행되는 것을 막으려면 if문으로 조건을 추가해주는  방법이 있다

useEffect(() => {
  if (keyword.length > 0) {
    console.log("SEARCH FOR", keyword);
  }
}, [keyword]);

예제 - useEffect 작동 확인

import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => {
    setKeyword(event.target.value);
  };
  console.log("I run all the time");
  useEffect(() => {
    console.log("I run only once");
  }, []);
  useEffect(() => {
    console.log("I run when 'keyword' changes.");
  }, [keyword]);
  useEffect(() => {
    console.log("I run when 'counter' changes.");
  }, [counter]);
  useEffect(() => {
    console.log("I run when 'keyword' and 'counter' changes.");
  }, [keyword, counter]);
  return (
    <div>
      <input
        value={keyword}
        onChange={onChange}
        type="text"
        placeholder="Search here"
      ></input>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

cleanup function

react는 컴포넌트를 destroy할 때도 함수를 사용 가능

아래 코드에서 Hello 컴포넌트가 사라질 때, useEffect 안의 함수의 return문이 실행

- Nico는 거의 사용하지 않는다고 했음

import { useEffect, useState } from "react";

function Hello() {
  useEffect(() => {
    console.log("created!");
    return () => console.log("detroyed!");
  }, []);
  return <h1>Hello</h1>;
}

function App() {
  const [showing, setShowing] = useState(false);
  const onClick = () => setShowing((prev) => !prev);
  return (
    <div>
      {showing ? <Hello /> : null}
      <button onClick={onClick}>{showing ? "Hide" : "Show"}</button>
    </div>
  );
}

export default App;

Component Life Cycle

위의 useEffect는 React에서 Hooks라는 개념

이 이전에는 React를 class 형태로 사용했었다. 

  • Mounting
    • constructor: render 되기 전에 호출
    • componentDidMount: component가 처음 rendering되었을 때 실행, useEffect의 dependencies가 빈 리스트일 경우와 동일
  • Updating
    • componentDidUpdate: state가 변경점이 생겨, 새로 rendering된 경우에 실행
  • Unmounting
    • componentWillUnmount: component가 사라질 경우에 호출 (페이지 이동 시)
import React from "react";

class App extends React.Component {
  componentDidMount() {
    console.log("component rendered");
  }
  render() {
    console.log("I am rendering");
    return;
  }
}

export default App;
// Result
// I am rendering
// component rendered

 

'React' 카테고리의 다른 글

[React 기초] 07. 예제 - Coin tracker  (0) 2023.08.10
[React 기초] 06. 예제 - Todo List  (0) 2023.08.10
[React 기초] 04. create-react-app  (0) 2023.08.10
[React 기초] 03. Props  (0) 2023.08.02
[React 기초] 02. State  (0) 2023.08.02