Web Tech/react

react 기본 - 13.useEffect

걍가영 2021. 11. 23. 16:48

useEffect
react Hook 중 useEffect는 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있게 합니다.
마운트 될 때(처음 나타났을때), 언마운트 됐을 때(사라질때), 업데이트 될 때(특정 props가 바뀔 때) 특정 작업을 처리할 수 있습니다.

기본형태
useEffect(function, deps)
> function : 수행하고자 하는 작업

> deps : 배열 형태, 배열 안에는 검사하고자 하는 특정 값 or 빈 배열
**deps 를 생략한다면 렌더링 될 때 마다 실행됨**


1. 마운트 될 때
컴포넌트가 처음 나타날때에만 useEffect에 등록한 함수가 호출됩니다.
> props 로 받은 값을 컴포넌트의 로컬 상태로 설정
> 외부 API 요청
> 라이브러리 사용
> setInterval 을 통한 반복작업 혹은 setTimeout 을 통한 작업 예약

// useEffect 불러오기
import React,{useEffect} from 'react';

useEffect(() => {
	console.log('마운트(처음) 될 때만 실행')
}, []);

2. 언마운트 될 때 & update 되기 직전에
cleanup 함수가 반환되며, useEffect에 대한 뒷정리 함수라고 생각하면 된다.
cleanup은 deps 가 비어있는 경우에는 컴포넌트가 사라질때 호출된다.

> setInterval, setTimeout 을 사용하여 등록한 작업들 clear(clearInterval, clearTimeout) 하기
> 라이브러리 인스턴스 제거

// useEffect 불러오기
import React,{useEffect} from 'react';

useEffect(() => {
	console.log('user 값이 설정됨',user)
	return () => {
	console.log('user가 바뀌기 전',user)
    }
}, []);

3. 업데이트 될 때
deps에 특정 값을 넣게 된다면, 컴포넌트가 처음 마운트 될 때와 지정한 값이 바뀔 때에도 호출이 됩니다.
useEffect에 deps를 넣지 않으면  useEffect에 등록한 함수가 실행 될 때 최신 props 상태를 가르키지 않습니다.

// useEffect 불러오기
import React,{useEffect} from 'react';

useEffect(() => {
	console.log('user 값이 설정됨',user)
    return () => {
       console.log('user가 바뀌기 전',user)
    }
}, [user]);

UserList.js

import React,{useEffect} from 'react';

const User = ({user, onRemove, onToggle}) => {
    useEffect(() => {
        console.log('user 값이 설정됨',user)
        return () => {
            console.log('user가 바뀌기 전',user)
        }
    }, [user]);
    return(
        <>
            <p><b onClick={() => onToggle(user.id)} style={{cursor:'pointer', color: user.active ? 'green' : 'black'}}>{user.username}</b> "{user.email}" <button onClick={() => onRemove(user.id)} type="button">삭제</button></p>
        </>
    )
}

const UserList = ({users, onRemove, onToggle}) => {
    return (
        <>
            {users.map(user => (
                <User user={user} key={user.id} onRemove={onRemove} onToggle={onToggle}/>
            ))}
        </>
    )
}

export default UserList;

App.js 

import React, {useRef, useState} from 'react';
import Inner from "./Inner";
import UserList from "./UserList";
import CreateUser from "./CreateUser";

function App() {
    const [inputs, setInputs] = useState({
       usersname: '',
       email: ''
    });

    const {username, email} = inputs;

    const onChange = e => {
        const {name,value} = e.target;
        setInputs({
           ...inputs,
           [name]: value
        });
    }
    const [users, setUsers] = useState ([
        {
            id: 1,
            username: 'a',
            email : 'aaa@gmail.com',
            active: true
        },
        {
            id: 2,
            username: 'b',
            email : 'bbb@gmail.com',
            active: false
        },
        {
            id: 3,
            username: 'c',
            email : 'ccc@gmail.com',
            active: false
        }
    ]);
    const nextId = useRef(4);

    const onCreate = () => {
        const user = {
            id: nextId.current,
            username,
            email
        }
        setUsers([...users, user]);
        setInputs({
           username: '',
           email: ''
        });
        nextId.current += 1;
    }

    const onRemove = id => {
        setUsers(users.filter(user => user.id !== id));
    }

    const onToggle = id => {
        setUsers(
            users.map(user => user.id === id ? {...user, active: !user.active} : user )
        )
    }
    return (
        <React.Fragment>
            <Inner>
                <CreateUser
                    username={username}
                    email={email}
                    onChange={onChange}
                    onCreate={onCreate}
                />
                <UserList users={users} onRemove={onRemove} onToggle={onToggle}/>
            </Inner>
        </React.Fragment>
    );
}

export default App;