Context API 사용한 전역 값 관리

라용·2023년 1월 10일
0

벨로퍼트와 함께하는 모던 리액트 내용을 정리한 내용입니다.

아래처럼 특정 함수를 전달하는 용도의 중간다리 역할을 하는 컴포넌트가 있을 수 있습니다.

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

이런 전달이 여러번 되는 것을 방지하고자, Context API 를 사용해 전역적으로 상태를 관리할 수 있습니다. 상태가 아닌 함수나 외부 라이브러리 인스턴스, DOM 일 수도 있기 때문에 상태보다는 값이라고 표현할 수 있습니다.

Context 는 React.createContext() 라는 함수를 사용해 생성합니다.

const UserDispatch = React.createContext(null);

Context 를 만들면 Context 안에 Provider 라는 컴포넌트가 들어있고, 이 컴포넌트를 통해 Context 의 값을 정할 수 있습니다. value 라는 값을 아래처럼 설정해주면 됩니다.

<UserDispatch.Provider value={dispatch}>...</UserDispatch.Provider>

이렇게 설정하면 Provider 에 감싸진 컴포넌트 중 어디서든지 우리가 Context 의 값을 다른 곳에서 바로 조회하고 바로 사용할 수 있습니다.

기존 작업하던 App 컴포넌트에 Context API 의 틀을 잡아보면

..

// UserDispatch 라는 이름으로 내보내줍니다.
export const UserDispatch = React.createContext(null);

function App() {
  ..

  const count = useMemo(() => countActiveUsers(users), [users]);
  return (

    // 이렇게 감싸준다.
    <UserDispatch.Provider value={dispatch}>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} onToggle={onToggle} onRemove={onRemove} />
      // 위에처럼 onToggl, onRemove 를 보내지 않게.. 아래 더 정리해보면,
      <div>활성사용자 수 : {count}</div>
    </UserDispatch.Provider>
  );
}

export default App;

위에처럼 export 를 하면 필요할 때 import 해서 사용할 수 있습니다.

export const UserDispatch = React.createContext(null);

// 아래처럼 가져와서 사용

import { UserDispatch } from './App';

Context 를 만들었다면 onToggle, onRemove 를 없애도 됩니다. Context API 를 활용해 해당 함수의 역할을 할 디스패치를 그 위치에서 바로 호출할 수 있기 때문입니다.

..

// UserDispatch 라는 이름으로 내보내줍니다.
export const UserDispatch = React.createContext(null);

function App() {
  ..

  const count = useMemo(() => countActiveUsers(users), [users]);
  return (

    // 이렇게 감싸준다.
    <UserDispatch.Provider value={dispatch}>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users}/>
      // onToggl, onRemove 제거
      <div>활성사용자 수 : {count}</div>
    </UserDispatch.Provider>
  );
}

export default App;

이제 UserList 컴포넌트 안의 User 컴포넌트에서 디스패치를 바로 호출해서 사용합니다. 그러기 위해 useContext 라는 Hook 을 사용하고 UserDispatch Context 를 조회해야 합니다.

import React, { useContext } from 'react';
import { UserDispatch } from './App';

const User = React.memo(function User({ user }) {
  const dispatch = useContext(UserDispatch);

  return (
    <div>
      <b
        style={{
          cursor: 'pointer',
          color: user.active ? 'green' : 'black'
        }}
        onClick={() => {
          dispatch({ type: 'TOGGLE_USER', id: user.id });
        }}
      >
        {user.username}
      </b>
      &nbsp;
      <span>({user.email})</span>
      <button
        onClick={() => {
          dispatch({ type: 'REMOVE_USER', id: user.id });
        }}
      >
        삭제
      </button>
    </div>
  );
});

function UserList({ users }) {
  return (
    <div>
      {users.map(user => (
        <User user={user} key={user.id} />
      ))}
    </div>
  );
}

export default React.memo(UserList);

이런식으로 어디서든 dispatch 를 조회하고 사용할 수 있습니다.

profile
Today I Learned

0개의 댓글