[React] useReducer 를 활용한 출석부

DongHyeon Jung·2022년 10월 14일
0

React

목록 보기
12/15
post-thumbnail

회고

  • reducer함수에는 주로 if문과 switch문이 사용된다
  • dispatch 내 action의 내용은 여러가지가 있는데 type, payload, id를 주로 사용한다
    - type은 reducer 함수 내의 switch문을 사용할 때 주로 사용된다(어떤 행동인지 알려줌)
    - payload는 전송하고자 하는 데이터의 핵심이 무엇인지 알려준다
    - id는 식별하기 위한 목적으로 전달한다
    { type: 'add-student', payload: { name } } 의 예시처럼
  • useReducer의 initial state로 useState에 비해 복잡한 state가 들어간다
const initialState = {
	count: 0,
	students: [],
};

예제 코드

App.js

import React, { useState, useReducer } from 'react';
import Students from './Students';

const reducer = (state, action) => {
  switch (action.type) {
    case 'add-student':
      const name = action.payload.name;
      const newStudent = {
        id: Math.random(),
        name,
        pretend: false,
      };
      return {
        count: state.count + 1,
        students: [...state.students, newStudent],
      };
    case 'delete-student':
      return {
        count: state.count - 1,
        students: state.students.filter(
          student => student.id !== action.payload.id
        ),
      };
    case 'mark-student':
      return {
        count: state.count,
        students: state.students.map(student => {
          if (student.id === action.payload.id) {
            return { ...student, pretend: !student.pretend };
          }
          return state;
        }),
      };
    default:
      return state;
  }
};

// complicated states => reducer(initialState)
const initialState = {
  count: 0,
  students: [],
};

function App() {
  const [name, setName] = useState('');
  const [studentsInfo, dispatch] = useReducer(reducer, initialState);
  return (
    <div>
      <h1>출석부</h1>
      <p>학생수: {studentsInfo.count}</p>
      <input
        type="text"
        placeholder="input name"
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <button
        onClick={() => {
          // dispatch(action)
          dispatch({ type: 'add-student', payload: { name } });
        }}
      >
        추가하기
      </button>
      {studentsInfo.students.map(student => (
        <Students
          key={student.id}
          name={student.name}
          dispatch={dispatch}
          id={student.id}
          pretend={student.pretend}
        />
      ))}
    </div>
  );
}

export default App;

Students.js

import React from 'react';

const Students = ({ name, dispatch, id, pretend }) => {
  return (
    <div>
      <span
        style={{
          textDecoration: pretend ? 'line-through' : 'none',
          color: pretend ? 'gray' : 'black',
          cursor: 'pointer',
        }}
        onClick={() => {
          dispatch({ type: 'mark-student', payload: { id } });
        }}
      >
        이름: {name}
      </span>
      <button
        onClick={dispatch({
          type: 'delete-student',
          payload: { id },
          pretend: { pretend },
        })}
      >
        삭제하기
      </button>
    </div>
  );
};

export default Students;

0개의 댓글