7-5. 프로젝트 기초공사 2 (프로젝트 상태관리 기초 공사하기)

2022. 8. 10. 15:31React/한입 크기로 잘라 먹는 리액트(React.js)

🚧기초 공사 항목

1. 상태 관리 세팅하기

프로젝트 전반적으로 사용 될 일기 데이터 Satate 관리 로직 작성하기

2. 프로젝트 State Context 세팅하기

일기 데이터 State를 공급할 Context를 생성하고 Provider로 공급하기

3. 프로젝트 Dispatch context 세팅하기

일기 데이터 State의 Dispatch 함수들을 공급할 Context를 생성하고 Provider로 공급하기

 

 

1. 상태 관리 세팅하기

프로젝트 전반적으로 사용 될 일기 데이터 Satate 관리 로직 작성하기

자 일기데이터에 각각 적용할 state들을 작성해보자.

useReducer를 사용해서 작성해보자.

import { useReducer, useRef } from 'react';

import './App.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';

import Home from './pages/Home'
import New from './pages/New'
import Edit from './pages/Edit'
import Diary from './pages/Diary'

const reducer = (state, action) => {
  let newState = [];
  switch (action.type) {
    case 'INIT': {
      return action.data;
    }
    case 'CREATE': {
      // const newItem = {
      //   ...action.data
      // };
      newState = [action.data, ...state];
      // default까지 return 하지 않으려면 break걸어줘야함
      break;
    }
    case 'REMOVE': {
      newState = state.filter((it) => it.id !== action.targetId);
      break;
    }
    case 'EDIT': {
      // content만 바꾸는게 아니라 전체를 바꿀거기 때문에
      newState = state.map((it) => it.id === action.data.id ? { ...action.data } : it);
      break;
    }
    default:
      return state;
  }
  return newState;
}

function App() {
  const [data, dispatch] = useReducer(reducer, []);

  const dataId = useRef(0);
  // CREATE
  // date는 언제 작성된것 까지 받을 거기 때문에 입력
  const onCreate = (date, content, emotion) => {
    dispatch({
      type: "CREATE",
      data: {
        id: dataId.current,
        date: new Date(date).getTime(),
        content,
        emotion,
      }
    });
    dataId.current += 1;
  };  
  // REMOVE
  const onRemove = (targetId) => {
    dispatch({ type: "REMOVE", targetId });
  }
  // EDIT
  // id만 유지하면서 다른이들은 변경
  const onEdit = (targetId, date, content, emotion) => {
    dispatch({
      type: "EDIT",
      date: {
        id: targetId,
        date: new Date(date).getTime(),
        content,
        emotion,
      },
    });
  };
  
  return (
    <BrowserRouter>
      <div className="App">
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/new" element={<New />} />
          <Route path="/edit" element={<Edit />} />
          <Route path="/diary/:id" element={<Diary />} />
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

2. 프로젝트 State Context 세팅하기

일기 데이터 State를 공급할 Context를 생성하고 Provider로 공급하기

상태관리로직에 Context를 만들어 data state 를 컴포넌트 트리 전역에 생성하여 공급해보자.

import React, { useReducer, useRef } from 'react';

import './App.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';

import Home from './pages/Home'
import New from './pages/New'
import Edit from './pages/Edit'
import Diary from './pages/Diary'

const reducer = (state, action) => {
  let newState = [];
  switch (action.type) {
    case 'INIT': {
      return action.data;
    }
    case 'CREATE': {
      // const newItem = {
      //   ...action.data
      // };
      newState = [action.data, ...state];
      // default까지 return 하지 않으려면 break걸어줘야함
      break;
    }
    case 'REMOVE': {
      newState = state.filter((it) => it.id !== action.targetId);
      break;
    }
    case 'EDIT': {
      // content만 바꾸는게 아니라 전체를 바꿀거기 때문에
      newState = state.map((it) => it.id === action.data.id ? { ...action.data } : it);
      break;
    }
    default:
      return state;
  }
  return newState;
}

export const DiaryStateContext = React.createContext();

function App() {
  const [data, dispatch] = useReducer(reducer, []);

  const dataId = useRef(0);
  // CREATE
  // date는 언제 작성된것 까지 받을 거기 때문에 입력
  const onCreate = (date, content, emotion) => {
    dispatch({
      type: "CREATE",
      data: {
        id: dataId.current,
        date: new Date(date).getTime(),
        content,
        emotion,
      }
    });
    dataId.current += 1;
  };  
  // REMOVE
  const onRemove = (targetId) => {
    dispatch({ type: "REMOVE", targetId });
  }
  // EDIT
  // id만 유지하면서 다른이들은 변경
  const onEdit = (targetId, date, content, emotion) => {
    dispatch({
      type: "EDIT",
      date: {
        id: targetId,
        date: new Date(date).getTime(),
        content,
        emotion,
      },
    });
  };
  
  return (
    <DiaryStateContext.Provider value={data}>
      <BrowserRouter>
        <div className="App">
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/new" element={<New />} />
            <Route path="/edit" element={<Edit />} />
            <Route path="/diary/:id" element={<Diary />} />
          </Routes>
        </div>
      </BrowserRouter>      
    </DiaryStateContext.Provider>
  );
}

export default App;

 

3. 프로젝트 Dispatch context 세팅하기

일기 데이터 State의 Dispatch 함수들을 공급할 Context를 생성하고 Provider로 공급하기

import React, { useReducer, useRef } from 'react';

import './App.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';

import Home from './pages/Home'
import New from './pages/New'
import Edit from './pages/Edit'
import Diary from './pages/Diary'

const reducer = (state, action) => {
  let newState = [];
  switch (action.type) {
    case 'INIT': {
      return action.data;
    }
    case 'CREATE': {
      // const newItem = {
      //   ...action.data
      // };
      newState = [action.data, ...state];
      // default까지 return 하지 않으려면 break걸어줘야함
      break;
    }
    case 'REMOVE': {
      newState = state.filter((it) => it.id !== action.targetId);
      break;
    }
    case 'EDIT': {
      // content만 바꾸는게 아니라 전체를 바꿀거기 때문에
      newState = state.map((it) => it.id === action.data.id ? { ...action.data } : it);
      break;
    }
    default:
      return state;
  }
  return newState;
}

export const DiaryStateContext = React.createContext();
export const DiaryDispatchContext = React.createContext();

function App() {
  const [data, dispatch] = useReducer(reducer, []);

  const dataId = useRef(0);
  // CREATE
  // date는 언제 작성된것 까지 받을 거기 때문에 입력
  const onCreate = (date, content, emotion) => {
    dispatch({
      type: "CREATE",
      data: {
        id: dataId.current,
        date: new Date(date).getTime(),
        content,
        emotion,
      }
    });
    dataId.current += 1;
  };  
  // REMOVE
  const onRemove = (targetId) => {
    dispatch({ type: "REMOVE", targetId });
  }
  // EDIT
  // id만 유지하면서 다른이들은 변경
  const onEdit = (targetId, date, content, emotion) => {
    dispatch({
      type: "EDIT",
      date: {
        id: targetId,
        date: new Date(date).getTime(),
        content,
        emotion,
      },
    });
  };
  
  return (
    
    <DiaryStateContext.Provider value={data}>
      <DiaryDispatchContext.Provider
        value={{ onCreate, onEdit, onRemove }}
      >
        <BrowserRouter>
          <div className="App">
            <Routes>
              <Route path="/" element={<Home />} />
              <Route path="/new" element={<New />} />
              <Route path="/edit" element={<Edit />} />
              <Route path="/diary/:id" element={<Diary />} />
            </Routes>
          </div>
        </BrowserRouter>      
      </DiaryDispatchContext.Provider>
    </DiaryStateContext.Provider>
  );
}

export default App;