본문 바로가기

인강/노마드코더

[노마드코더] React Hooks

https://www.youtube.com/watch?v=G3qglTF-fFI&list=PLZ5oZ2KmQEYjwhSxjB_74PoU6pmFzgVMO&index=1

 

✅ useState

초기값이 연산이 많이 필요하다면

콜백함수를 사용하여 return하자.

=> 렌더링이 한번만 일어남.

const Init = () => {
	const heavyCost = "오래걸리는 작업";
    
    return heavyCost;
};

const App = () => {
	const [value, setValue] = useState(Init());
	
};

 

✅ useEffect

Mount: 화면에 첫 렌더링

Update: 다시 렌더링

Unmount: 화면에서 사라질 때

 

deps: dependency array

 

1. useEffect 인자가 콜백함수만 있는 경우: 항상 렌더링됨.

2. cleanUp: 화면에서 사라질 때, return문이 실행된다.

useEffect(()=>{
	const timer = setInterval(() => {
    	console.log("타이머 작동 중...");
    }, 1000);
    
	// cleanUP 작업(정리 작업)을 코딩한다.
	return () => {
    	clearInterval(timer);
        console.log("타이머가 종료되었습니다.");
    };
}, []);

 

 

✅ useRef

 

const ref = useRef(value);

 

ref

{current : value}

 

ref.current = "hi";

=> 언마운트되기 전까지 값을 유지한다.


 

1. 저장공간: state와 비슷하게 값을 저장하는데 사용한다.

state 값이 바뀔 때 렌더링이 되면서 초기화되지만, ref는 값이 바뀔 때 렌더링되지 않아 초기화되지 않는다.

=> 엄청 자주 바뀌는 값을 useRef를 사용하여 저장하고 원하는 때 한 번의 렌더링으로 값을 나타내자.

2. DOM 요소에 접근: input태그에 자동으로 focus하게 할 수 있다.

const App = () => {
	const inputBar = useRef(null);
    
    useEffect(() => {
    	inputBar.current.focus();
    },[]);
    
    return(
    	<div>
        	<input ref={inputBar} type="text" placeholder="username" />
        </div>
    );
};

 

 

✅ useContext

Prop Drilling: 데이터가 필요한 컴포넌트까지 props가 중간 컴포넌트들을 지나 전달되는 것

=> 불필요한 prop 전달, 코드 수정 어려움.

Context는 꼭 필요할 때만! prop drilling을 피하기만 위해서라면 Component Composition을 우선 고려해보자!!!

=> 컴포넌트 재사용이 어려워짐.

 

👀 useContext 사용법

export const ThemeContext = createContext(null);
const App = () => {
	<ThemeContext.Provider value={{ isDark, setIsDark }}>
		<Page />
	</ThemeContext.Provider>
}
const {isDark, setIsDark} = useContext(ThemeContext);

필요한 컴포넌트에서 props가 아닌 useContext를 활용하여 사용할 수 있다.

 

 

✅ useMemo

Memoizatioin: 동일한 값을 return하는 함수를 반복적으로 사용할 때 첫 연산 후 메모리에 저장해두고 재사용하자.

=> 필요할 때 다시 계산하는게 아니라 캐시해서 다시 사용하자.

    const name = useMemo(() => {
    	return {
        	lastName: '홍',
            firstName: '길동',
        };
    }, []);

😎 콜백함수가 return 하는 값이 useMemo를 사용하는 변수가 가지는 값이다.

변수에 Object를 저장하는 경우  → 렌더링 될 때마다 새로운 Object으로 인식함. 각각 다른 메모리 주소에 저장됨.

 

 

✅ useCallback

함수를 변수에 저장한다 : 저장공간 (메모리) 어딘가에 함수가 저장되고 메모리 주소가 변수에 저장된다. 변수가 함수를 참조하고 있다.

    const tellMe = useCallback(() => {
    	console.log("길동아 사랑해!");
    }, []);

😎 콜백함수가 그 자체가 useCallback를 사용하는 변수가 참조하는 함수이다.

변수에 Function를 저장하는 경우 → 렌더링 될 때마다 새로운 Function으로 인식함. 각각 다른 메모리 주소에 저장됨.

 

 

✅ useReducer

useState와 비슷하게 state관리를 위한 또 다른 훅,

여러 개의 복잡한 하위 state를 다룰 때 사용한다.

    const [requestData, setrequestData] = useState({
        estimate_id: 10,
        user_info: {
            user_id: 0,
            user_name: "",
            level: 0
        },
        title: "",
        created_at: "",
        video: "",
        content: "",
        dead_line: "",
        status: 0
    });

 

Reducer: 사용자가 직접 state를 업데이트 하는 것은 불가능하다. Reducer가 state를 업데이트 해준다.

=> state를 업데이트 하는 역할

Dispatch: Reducer에게 update를 요구하는 것.

=> state 업데이트를 위한 요구

Action: state를 어떻게 update 할 건지 내용.

=> 요구의 내용

 

reducer는 action대로만 행동한다. reducer에서 미리 정해진 행동대로만 행동한다. (예상할 수 있다)

 

 

✅ React.memo (ft. useMemo, useCallback)

Prop Check: 컴포넌트가 전달받는 props를 확인하여 props가 변경될 때만 렌더링하자. 변경되지 않았다면 memoization한 것 재사용.

1. 컴포넌트가 같은 props로 자주 렌더링 될 때

2. 컴포넌트가 렌더링 될 때마다 복잡한 로직을 처리하는 경우

 

<React.StrictMode/>: 개발할 때 켜두면 여러 에러를 잡아줘서 좋음. 콘솔을 보기 위해 잠시 제거함.

 

React.memo: 고차 컴포넌트(HOC). 보다 최적화된 컴포넌트를 배출함.

import {memo} from 'react';

const Child = () => {

};

export default memo(Child);

=> 컴포넌트가 렌더링 상황에 놓일 때마다 Prop Check를 함.

 

 

✅ Custom Hooks

Custom Hook을 사용하는 컴포넌트마다 Custom Hook이 가지는 state와 effect는 각 컴포넌트마다 완전히 독립적이기 때문에 재활용성이 높다.

=> useInput, useFetch

 

✅ useId

    return (
        <div>
            <label htmlFor='name'>이름</label>
            <input id='name'/>
        </div>
    );
    const id = useId();
    return (
        <div>
            <label htmlFor={id}>이름</label>
            <input id={id} />
        </div>
    );
    const id = useId();
    return (
        <div>
            <label htmlFor={`${id}-name`}>이름</label>
            <input id={`${id}-name`} />
            <br/>
            <label htmlFor={`${id}-age`}>이름</label>
            <input id={`${id}-age`} />
        </div>
    );
    const id = useId();
    const ref = useRef();
    
    useEffect(() = > {
        const element = ref.current;
        console.log(element);    //querySelector를 사용하지 않는다.
    }, []);
    
    return (
        <div>
            <button id="btn">버튼</button>
            <label htmlFor={id}>이름</label>
            <input id={id} ref={ref}/>
        </div>
    );

=> 접근성, 안정성 향상, DOM 요소 접근