Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

개발자의 자기계발 블로그( ੭ ・ᴗ・ )੭

[React] Hook의 개념, 그리고 주요 Hook (UseState, UseEffect) 본문

JS

[React] Hook의 개념, 그리고 주요 Hook (UseState, UseEffect)

쪼사원 2024. 6. 24. 11:15

목차

    ✅ 리액트 훅 (Hook)

    함수형 컴포넌트에서 상태(state)와 생명주기(Lifecycle) 기능을 사용할 수 있게 해주는 기능이다.

    원래 있던 기능은 아니고 리액트 16.8에서 도입되었는데,

    이를 통해 클래스형 컴포넌트의 필요성을 줄이고 코드의 가독성과 재사용성을 높일 수 있게 되었다.

     

    ✅ 주요 훅 소개

    1. useState

    • 상태 변수를 선언하고 관리하는 훅
    • 함수형 컴포넌트 내에서 상태를 사용할 수 있게 해줌
    import React, {useState} from "react";
    
    function Counter(){
        const [count, setCount] = useState(0);
    
        return (
            <div>
                <p>You clicked {count} times</p>
                <button onClick = {() => setCount(count + 1)}>Click me</button>
            </div>
        );
    }

    - count는 현재 상태 값을 나타냄

    - setCount는 상태 값인 count를 갱신하는 함수

      setCount(newCount)를 호출하면 count가 newCount로 업데이트되고 컴포넌트가 다시 렌더링 됨

    - useState(0) : 상태의 초기 값을 0으로 설정

     

    2. useEffect

    • side effects를 수행할 때 사용하는 훅
    • 데이터 가져오기(fetching data), 구독(subscription) 설정, 수종으로 리액트 컴포넌트 업데이트, 타이머 설정 등의 작업을 처리할 수 있음

    🔽 예제 1. 의존성 배열이 없는 useEffect 훅 (1)

    import './App.css';
    import {useState, useEffect} from 'react';
    import Timer from './component/Timer';
    
    function App() {
    
      const [count, setCount] = useState(1);
    
      const handleCountUpdate = () => {
        setCount(count + 1);
      };
    
      // 렌더링 될 때마다 매번 실행
      useEffect(() => {
        console.log('렌더링!');
      })
    
      return (
        <div>
          <button onClick={handleCountUpdate}>Update</button>
          <span>count: {count}</span>
        </div>
      );
    }
    
    export default App;

    ▶ Update 버튼을 누를 때마다 count가 1씩 증가하면서 콘솔에 '렌더링' 이라는 로그가 매번 찍힘

    useEffect 훅에서 두번째 인자. 즉,  의존성 배열이 생략된 경우 컴포넌트가 업데이트 될 때마다 렌더링 되는 것을 확인할 수 있음

     

    🔽 예제 2. 의존성 배열이 없는 useEffect 훅 (2)

    import './App.css';
    import {useState, useEffect} from 'react';
    import Timer from './component/Timer';
    
    function App() {
    
      const [count, setCount] = useState(1);
      const [name, setName] = useState('');
    
      const handleCountUpdate = () => {
        setCount(count + 1);
      };
    
      const handleInputChange = (e) => {
        setName(e.target.value);
      };
    
      // 렌더링 될 때마다 매번 실행
      useEffect(() => {
        console.log('렌더링!');
      });
    
      return (
        <div>
          <button onClick={handleCountUpdate}>Update</button>
          <span>count: {count}</span><br />
          <input type='text' value={name} onChange={handleInputChange}/>
          <span>name: {name}</span>
        </div>
      );
    }
    
    export default App;

    ▶ 마찬가지로 컴포넌트가 업데이트 될 때마다(input박스 안에 글자를 변경할 때마다) 렌더링이 되는 것을 콘솔로 확인할 수 있음 !!


    위에 두 예제에서는 컴포넌트가 업데이트 될 때마다 useEffect가 실행되었는데,

    그게 아닌 특정한 경우에만 실행시키고 싶은 경우❓❓

     

    🔽 예제 3. 의존성 배열이 있는 useEffect 훅

    import './App.css';
    import {useState, useEffect} from 'react';
    import Timer from './component/Timer';
    
    function App() {
    
      const [count, setCount] = useState(1);
      const [name, setName] = useState('');
    
      const handleCountUpdate = () => {
        setCount(count + 1);
      };
    
      const handleInputChange = (e) => {
        setName(e.target.value);
      };
    
      // 마운트 될 때 + [ item ] 변경될 때만 실행
      useEffect(() => {
        console.log('count 변화!');
      }, [count]);
    
      return (
        <div>
          <button onClick={handleCountUpdate}>Update</button>
          <span>count: {count}</span><br />
          <input type='text' value={name} onChange={handleInputChange}/>
          <span>name: {name}</span>
        </div>
      );
    }
    
    export default App;

    ▶ 예제 2번 코드에서 useEffect() 부분만 바뀜.

    두번째 인자로 배열에 count를 넣어줌으로써 count가 변화할 때만 실행되도록 하였다.

    input태그에 이름을 입력해도 콘솔이 찍히지 않고 update버튼을 누를 시에만 콘솔이 찍히는 모습을 확인 할 수 있다.


    그러면 처음에 마운팅 될 때만 한 번 실행시키고 싶을 땐❓❓

    🔽 예제 4. 의존성 배열이 빈 배열일 경우

    import './App.css';
    import {useState, useEffect} from 'react';
    import Timer from './component/Timer';
    
    function App() {
    
      const [count, setCount] = useState(1);
      const [name, setName] = useState('');
    
      const handleCountUpdate = () => {
        setCount(count + 1);
      };
    
      const handleInputChange = (e) => {
        setName(e.target.value);
      };
    
      // 처음 마운팅 될 때 한 번만 실행
      useEffect(() => {
        console.log('마운팅 됨!!');
      }, []);
    
      return (
        <div>
          <button onClick={handleCountUpdate}>Update</button>
          <span>count: {count}</span><br />
          <input type='text' value={name} onChange={handleInputChange}/>
          <span>name: {name}</span>
        </div>
      );
    }
    
    export default App;

    ▶ 처음 마운트 될 때 로그가 찍히고 아무리 count를 update하고, name을 입력해도 아무 변화가 없는 것을 확인할 수 있다.

     

     

    ✅ UseEffect &  Clean Up - Timer

     

    clean up 메커니즘은 타이머나 구독(subsciptions) 등을 정리하는 데에 유용하다.

    setInterval이나 WebSocker 연결을 정리하는 데 사용할 수 있다.

    clean up 기능은 컴포넌트의 성능과 안정성을 유지하는 데 매우 중요한 역할을 함!!

    useEffect에서 return  함수 부분이 clean up 함수가 실행될 부분이 된다.

     

    🔽 예제. Timer를 예제로 Clean Up에 대하여 알아보자 !!

    예제 코드 구조

     

    App.js

    import './App.css';
    import {useState, useEffect} from 'react';
    import Timer from './component/Timer';
    
    function App() {
    
      const [showTimer, setShowTimer] = useState(false);
    
      return (
        <div>
          {/* 
              {<Timer /> && showTimer}로 작성하면 작동 안되는 이유 :
              && 문법은 왼쪽 피연산자가 true일 때만 오른쪽 피연산자를 리턴하는 문법임
          */}
          {showTimer && <Timer />}
          <button onClick={() => setShowTimer(!showTimer)}>Toggle Timer</button>
        </div>
      );
    }
    
    export default App;

    showTimer가 true 일때만 Timer 를 실행

     

    Timer.js

    import React, {useEffect} from "react";
    
    const Timer = () =>{
    
        // 타이머 컨포넌트가 화면에 처음 렌더링 될 때만 실행
        useEffect(() => {
            const timer = setInterval(() => {
                console.log('타이머 돌아가는중...')
            }, 1000);
    
            return () => {
                clearInterval(timer);
                console.log('타이머가 종료되었습니다.');
            };
        }, []);
    
        return (
            <div>
                <span>타이머를 시작합니다. 콘솔을 보세여</span>
            </div>
        );
    };
    
    export default Timer;

    return 함수 내부 내용은 컴포넌트가 언마운트 되기 전에 실행됨

     

     

    >> 혹시 마운트 하자마자 '타이머가 종료되었습니다' 로그가 찍힌다면???

    create-react-app으로 리액트 앱을 만들 시 index.js에 기본적으로 Strict mode가 추가되기 때문이다.

    Strict mode는 리액트로 개발할 때 코드 상에 문제점들을 미리 검사하고 콘솔에 알려주는 역할을 하여 한 번 더 실행이 된 것!!

    <StrictMode> 태그를 없애주면 해결이 된다❗

     

    ⭐ 정리!

     

     

    포스팅 참고 자료

    - 별코딩: React Hooks에 취한다 https://www.youtube.com/playlist?list=PLZ5oZ2KmQEYjwhSxjB_74PoU6pmFzgVMO

     

    React Hooks에 취한다 - 리액트 훅스 쉽게 마스터하기

     

    www.youtube.com

    - 인프런 : 처음 만난 리액트 https://inf.run/YehVc

     

    [지금 무료] 처음 만난 리액트(React) | Inje Lee (소플) - 인프런

    Inje Lee (소플) | 자바스크립트와 CSS 기초 문법과 함께 리액트의 기초를 탄탄하게 다질 수 있습니다., 깔끔한 강의자료, 꼼꼼한 설명으로쉽게 배우는 리액트 강의입니다. 👨‍🏫 리액트의 세계로

    www.inflearn.com

     

    'JS' 카테고리의 다른 글

    [React] 상태(State)와 생명주기(Lifecycle)  (0) 2024.06.19
    [React] Components와 Props  (0) 2024.06.18
    [React] Rendering Elements  (0) 2024.06.17
    [React] JSX  (0) 2024.06.17
    [React] 리액트 시작하기전에 & 소개  (0) 2024.06.14