const [isFancy, setIsFancy] = useState(false);
{isFancy ? (
<Counter isFancy={true} />
) : (
<Counter isFancy={false} />
)}

const [isPaused, setIsPaused] = useState(false);
{isPaused ? (
<p>See you later!</p>
) : (
<Counter />
)}

const [isPlayerA, setIsPlayerA] = useState(true);
{isPlayerA ? (
<Counter key="Taylor" person="Taylor" />
) : (
<Counter key="Sarah" person="Sarah" />
)}
예시 코드
import { useState } from 'react';
import AddTask from './AddTask.js';
import TaskList from './TaskList.js';
export default function TaskApp() {
const [tasks, setTasks] = useState(initialTasks);
function handleAddTask(text) {
setTasks([...tasks, {
id: nextId++,
text: text,
done: false
}]);
}
function handleChangeTask(task) {
setTasks(tasks.map(t => {
if (t.id === task.id) {
return task;
} else {
return t;
}
}));
}
function handleDeleteTask(taskId) {
setTasks(
tasks.filter(t => t.id !== taskId)
);
}
return (
<>
<h1>Prague itinerary</h1>
<AddTask
onAddTask={handleAddTask}
/>
<TaskList
tasks={tasks}
onChangeTask={handleChangeTask}
onDeleteTask={handleDeleteTask}
/>
</>
);
}
handleAddTask(text)handleChangeTask(task)handleDeleteTask(taskId)다음과 같은 형태로 변경한다.
dispatch({
// 컴포넌트마다 다른 값
type: 'what_happened',
// 다른 필드는 이곳에
});
변경 코드
function handleAddTask(text) {
dispatch({
type: 'added',
id: nextId++,
text: text,
});
}
function handleChangeTask(task) {
dispatch({
type: 'changed',
task: task
});
}
function handleDeleteTask(taskId) {
dispatch({
type: 'deleted',
id: taskId
});
}
다음과 같은 형태로 작성한다.
function yourReducer(state, action) {
// React가 설정하게될 다음 state 값을 반환합니다.
}
추가 코드
function tasksReducer(tasks, action) {
switch (action.type) {
case 'added': {
return [...tasks, {
id: action.id,
text: action.text,
done: false
}];
}
case 'changed': {
return tasks.map(t => {
if (t.id === action.task.id) {
return action.task;
} else {
return t;
}
});
}
case 'deleted': {
return tasks.filter(t => t.id !== action.id);
}
default: {
throw Error('Unknown action: ' + action.type);
}
}
}
// 기존
const [tasks, setTasks] = useState(initialTasks);
// 변경
import { useReducer } from 'react';
const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);
| useState | useReducer | |
|---|---|---|
| 코드 크기 | 미리 작성해야 하는 코드가 줄어든다. | reducer함수와 action 전달 부분을 작성해야하지만, 여러 이벤트 핸들러에서 비슷한 방식으로 state를 업데이트 하는 경우 코드의 양을 줄이는데 도움이 된다. |
| 가독성 | 간단한 state를 업데이트 하는 경우 가독성이 좋은 편이다. | 업데이트 로직이 어떻게 동작하는지와 이벤트 핸들러를 통해서 무엇이 발생했는지 명확하게 구분할 수 있다. |
| 디버깅 | 왜, 어디서 state가 잘못 설정됐는지 찾기 어렵다. | 콘솔 로그를 추가하여 확인 할 수 있다. 더 많은 코드를 단계별로 실행해서 디버깅해야 한다. |

// LevelContext.js
import { createContext } from 'react';
export const LevelContext = createContext(1);
import { useContext } from 'react';
import { LevelContext } from './LevelContext.js';
export default function Heading({ children }) {
const level = useContext(LevelContext);
// ...
}
<Section level={4}>
<Heading>Sub-sub-heading</Heading>
<Heading>Sub-sub-heading</Heading>
<Heading>Sub-sub-heading</Heading>
</Section>
import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
<section className="section">
<LevelContext.Provider value={level}>
{children}
</LevelContext.Provider>
</section>
);
}
import { useContext } from 'react';
import { LevelContext } from './LevelContext.js';
export default function Section({ children }) {
const level = useContext(LevelContext);
return (
<section className="section">
<LevelContext.Provider value={level + 1}>
{children}
</LevelContext.Provider>
</section>
);
}
import { createContext } from 'react';
export const TasksContext = createContext(null);
export const TasksDispatchContext = createContext(null);
import { TasksContext, TasksDispatchContext } from './TasksContext.js';
export default function TaskApp() {
const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);
// ...
return (
<TasksContext.Provider value={tasks}>
<TasksDispatchContext.Provider value={dispatch}>
...
</TasksDispatchContext.Provider>
</TasksContext.Provider>
);
}
<TasksContext.Provider value={tasks}>
<TasksDispatchContext.Provider value={dispatch}>
<h1>Day off in Kyoto</h1>
<AddTask />
<TaskList />
</TasksDispatchContext.Provider>
</TasksContext.Provider>
export default function TaskList() {
const tasks = useContext(TasksContext);
// ...
export default function AddTask({ onAddTask }) {
const [text, setText] = useState('');
const dispatch = useContext(TasksDispatchContext);
// ...
return (
// ...
<button onClick={() => {
setText('');
dispatch({
type: 'added',
id: nextId++,
text: text,
});
}}>Add</button>
// ...