아래 코드를 살펴보면 App 컴포넌트에서 onToggle
, onRemove
가 구현이 됭있고 이 함수들은 UserList 컴포넌트를 거쳐서 각 User 컴포넌트들에게 전달되고 있다.
지금과 같이 특정 함수를 특정 컴포넌트를 거쳐서 원하는 컴포넌트에 전달하는 작엄은 자주 발생 할 수 있는 작업이다. 하지만 전달하는 함수가 3~4개 이상의 컴포넌트를 거쳐서 전달하게 된다면 이는 매우 번거로울 것이다.
그럴 땐, 리액트의 Context API와 dispatch를 함께 사용하면 이러한 문제를 해결할 수 있다.
funtion App() {
const [state, dispatch] = useReducer(reducer, initialState);
const nextId = useRef(4);
const { users } = state;
const { username, email } = state.inputs;
const onChange = useCallback(e => {
const { name, value } = e.target;
dispatch({
type: 'CHANGE_INPUT',
name,
value
});
}, []);
const onCreate = useCallback(() => {
dispatch({
type: 'CREATE_USER',
user: {
id: nextId.current,
username,
email
}
});
nextId.current += 1;
}, [username, email]);
const onToggle = useCallback(id => {
dispatch({
type: 'TOGGLE_USER',
id
});
}, []);
const onRemove = useCallback(id => {
dispatch({
type: 'REMOVE_USER',
id
});
}, []);
const count = useMemo(() => countActiveUsers(users), [users]);
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onToggle={onToggle} onRemove={onRemove} />
<div>활성사용자 수 : {count}</div>
</>
);
}
function UserList({ users, onRemove, onToggle }) {
return (
<div>
{users.map(user => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
리액트의 Context API 를 사용하면, 프로젝트 안에서 전역적으로 사용 할 수 있는 값을 관리 할 수 있다. 여기서 "상태" 가 아닌 "값" 이라고 언급을 한 이유는 이 값은 꼭 상태를 가르키지 않아도 됩니다. 이 값은 함수일수도 있고, 어떤 외부 라이브러리 인스턴스일수도 있고 심지어 DOM 일 수도 있다.
export const UserDispatch = React.createContext(null);
createContext
의 파라미터에는 Context 의 기본값을 설정할 수 있다. 여기서 설정하는 값은 Context 를 쓸 때 값을 따로 지정하지 않을 경우 사용되는 기본 값이 된다.
<UserDispatch.Provider value={dispatch}>...</UserDispatch.Provider>