Context API - Custom hook 만들기

LNSol·2022년 10월 24일

React

목록 보기
3/10

GitHub-reactbasic

Context에 대해 새로 알게된 내용이 있어 정리해본다. 또 Context를 이용한 Custom Hook을 만들어보자!

count를 context에서 관리하는 예를 보자.

Context

// src/contexts/count-context.js

import { createContext, useContext, useState } from 'react';

const CountContext = createContext();

export const CountProvider = ({ children }) => {
	const [ count, setCount ] = useState(0);

	const plusCount = () => setCount((prev) => prev + 1);
	const minusCount = () => setCount((prev) => prev - 1);

	return (
		<CountContext.Provider value={{ count, plusCount, minusCount }}>
			{children}
		</CountContext.Provider>
	);
};
export const useCount = () => useContext(CountContext);

컨텍스트에 있는 count는 Counter 컴포넌트에서 사용하고, plusCount는 Plus, minusCount는 Minus 컴포넌트에서 사용한다고 가정해보자. 그리고 이 세 컴포넌트는 Container 컴포넌트의 children이다.

🚀 여기서 중요한 것은 setState를 바로 공유하지 않고, 상태를 변경하는 함수를 전달한다는 것이다. 🚀



Provider

Consumer가 될 컴포넌트를 Provider로 감싸면 Provider로 감싸진 하위 컴포넌트들은 컨텍스트에 접근할 수 있게된다.

import { CountProvider } from '../contexts/counter-context';
...
<CountProvider>
	<Counter />
	<Plus />
	<Minus />
	<Other />
</CountProvider>
<Other />
...


Consumer

context에서 관리되고 있는 count, plusCount, minusCount는 각각<Count, Plus, Minus 컴포넌트에서 쓰인다.

사용법 1.

import { CountContext } from '../contexts/counter-context';
...
return (
	<CountContext.Consumer>
		{(ctx) => {
			..ctx.count,
			..ctx.plusCount,
			..ctx.minusCount
		}}
	</CountContext.Consumer>
);
...

사용법 2.

// src/components/Count.js
import { useCount } from '@contexts/counter-context';

const Count = () => {
	const { count } = useCount();

	return <div>Count: {count}</div>
};
export default Count;
// src/components/MinusCount.js
import { useCount } from '@contexts/counter-context';

const MinusCount = () => {
	const { minusCount } = useCount();

	return <button onClick={minusCount}>-1</button>
};
export default MinusCount;
// src/components/PlusCount.js
import { useCount } from '@contexts/counter-context';

const PlusCount = () => {
	const { plusCount } =useCount();

	return <button onClick={plusCount}>+1</button>
};
export default PlusCount;

count, minusCount, plusCount는 컨텍스트에서 관리하고 있으며 이렇게 Counter를 사용하는 useCount라는 커스텀 훅으로 간단히 사용할 수 있다.


기본적으로 컴포넌트가 리렌더링되는 조건 중 하나가 자신의 state가 변경되는 경우이고, 또 다른 하나가 부모 컴포넌트가 리렌더링 되는 경우인데(props가 변경되는 경우도 컴포넌트가 리렌더링 됨.) counter-context에서 count를 useState로 관리한다. 즉 count값이 변경되면 CountProvider 컴포넌트가 리렌더링 되고 따라서 그 자식 컴포넌트인(children) Count, MinusCount, PlusCount가 전부 리렌더링 된다.

🚀 Context.Provider는 컴포넌트가 아니다. 따라서 count state가 변경된다 하더라도 children에 속하는 모든 하위 컴포넌트가 전부 리렌더링 되는 것은 아니다. useCount 훅을 사용하여 context에 접근하는 컴포넌트만 리렌더링된다!! 🚀

useCount 훅을 사용하지 않는 Other 컴포넌트가 CountProvider 하위에 위치한 경우 화면상 깜박거리며 표시되긴 하지만 콘솔을 확인해보면 첫 마운트 시에만 출력이 되었고 count가 변경되었을 땐 출력되지 않는 것을 확인할 수 있다.

0개의 댓글