React

2. Diary 만들기 (Redux-Toolkit, axios.post, get)

ji_su_04 2023. 2. 1. 15:43

이제 본격적으로 기능을 넣기 위해 redux-toolkit을 이용해보자.

 

우선 index.js부터 수정해주자.

<index.js>

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./config/configStore";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

reportWebVitals();

Provider로 <App/>을 감싸주게 되는데 여기서 Provider이 뭔지 알 필요가 있다.

 

Provider이란?

더보기

리액트로 컴포넌트를 만들 때 상태값 관리는 보통 props 또는 state로 관리한다. 리액트에는 사실 props와 state외에도 상태를 관리하는 속성이 있다. 상태 관리(state management) 라이브러리로 react-redux, mobx-react 또는 react-apollo 등이 있으며 현재 진행중인 프로젝트에서는 react-redux로 상태관리를 하고 있다. 또한 styled-components나 material-ui 등의 ui라이브러리에서도 이 context를 사용하고 있다. 보통 이러한 라이브러리를 이용하면 Provider라는 이름의 컴포넌트를 제공하는데 이 컴포넌트 안에서 context값을 핸들링 하고 있다.

즉, Provider의 역할은 우리의 App이 Redux.store에 접근할 수 있도록 해준다.

그 후에 config 폴더와 modules를 만들어 configStore.js와 diarys.js를 만들어준다.

 

<configStore.js>

import { configureStore } from "@reduxjs/toolkit";
import diarys from "../modules/diarys";

const store = configureStore({
  reducer: {
    diarys,
  },
});

export default store;
<diarys.js>

import { createSlice } from "@reduxjs/toolkit";

//initial states
const initialState = {
  diarys: [],
  isSucces: false,
  isLoading: false,
  error: null,
};

const diarysSlice = createSlice({
  name: "diarys",
  initialState,
  extraReducers: {},
});

export default diarysSlice.reducer;

configstore란?

더보기

Reducer에서 반환된 새로운 state를 Store라는 객체로 정리해 관리하는 곳.

Store는 Redux Toolkit configureStore에 객체 형식으로 reducer를 전달하여 만들 수 있다.

또한 기존에 createStore비슷하지만 ! 여기서 주의할 점은  {reducer: rootReducer} 로 만들어 주어서 넣어야한다.

(property의 명이 반드시 reducer, 그리고 createStore와 달리 Thunk, dev tool까지 자동을 등록)

createslice란?

더보기

각 reducer를 호출하여 초기 상태를 검색.
초기 상태를 정리해서 초기 상태 트리를 생성.

reducer의 처리를 정리한 combination 함수를 돌려준다. 

이제 여기까지 초기 셋팅을 마치고 json-server를 열어주자.

나같은 경우엔 db.json으로 생성을 했으니 json-server ./db.json --port 4000을 터미널에 입력해주면 된다.

 

Json-Server 란?

더보기

프론트앤드 개발을 진행하다보면 백앤드 api 호출 테스트를 해야되는 경우가 있다.

단순히 sleep 를 걸어서 josn 파일을 불러오게 하고 테스트를 해봐도 되지만 실제 웹통신으로 데이터를 호출테스트를 진행하는게 더 정확한 테스트가 가능하다.

Json-server 은 웹통신으로 api 테스트를 진행행하고 싶은데 백앤드 api 를 만들어 사용하기 번거로울때 간단하게 셋팅 후 api 테스트를 해볼수 있는 기능을 제공한다.

db.json의 로컬을 실행하면 우선 아무 값도 나오지 않는다.

아직 아무런 값도 설정해주지 않았기 때문이다.

이제 방금 만든 diarys.js에 axios를 이용해서 json-server에 값을 넣어줘보자.

<diary.js>

export const __addDiaryThunk = createAsyncThunk(
  "ADD_DIARY",
  async (arg, thunkAPI) => {
    try {
      //시도 내용
      const response = await axios.post("http://localhost:4000/diarys", arg);
      console.log("response", response);
      return thunkAPI.fulfillWithValue(response.data);
    } catch (err) {
      return thunkAPI.rejectWithValue(err);
    }
  }
);
<Input.jsx>

const Input = () => {
  const dispatch = useDispatch();
  const [date, setDate] = useState("");
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");
  const handleDateChange = (event) => {
    setDate(event.target.value);
  };
  const handleTitleChange = (event) => {
    setTitle(event.target.value);
  };
  const handleContentChange = (event) => {
    setContent(event.target.value);
  };

  const handleSubmitButton = (event) => {
    event.preventDefault();
    const newDiary = {
      date,
      title,
      content,
    };
    dispatch(__addDiaryThunk(newDiary));
    setDate("");
    setTitle("");
    setContent("");
  };

  return (
    <InputDiv>
      <form onSubmit={handleSubmitButton}>
        <InputDate
          placeholder="날짜"
          id="date"
          value={date}
          onChange={handleDateChange}
        />
        <InputTitle
          placeholder="제목"
          id="title"
          value={title}
          onChange={handleTitleChange}
        />
        <InputContent
          placeholder="내용"
          id="content"
          value={content}
          onChange={handleContentChange}
        />
        <InputButton type="submit">완료</InputButton>
      </form>
    </InputDiv>
  );
};

axios 비동기 통신의 post를 이용해서 추가를 구현해주자.

Input.jsx에서도 date, title, content를 넣어줄 useState를 만들어주고 onSubmit에는 dispatch를 이용해서 방금 만든 addDiaryThunk를 넘겨주자.

그러고 버튼을 눌러주면 콘솔에 정상적으로 입력한 데이터 값이 담긴 것을 확인할 수 있다.

그럼 이제 이 입력 값들을 불러오는 기능인 get을 활용해보자.

//조회
export const __getDiarys = createAsyncThunk(
  "GET_TODOS",
  async (arg, thunkAPI) => {
    try {
      const diarys = await axios.get("http://localhost:4000/diarys");
      return thunkAPI.fulfillWithValue(diarys.data);
    } catch (err) {
      return thunkAPI.rejectWithValue(err);
    }
  }
);

const diarysSlice = createSlice({
  name: "diarys",
  initialState,
  extraReducers: {
    [__getDiarys.fulfilled]: (state, action) => {
      state.diarys = action.payload;
    },
    [__addDiaryThunk.fulfilled]: (state, action) => {
      state.diarys.push(action.payload);
    },
  },
});
<Diary.jsx>

const Diary = () => {
  const diarys = useSelector((state) => state.diarys.diarys);
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(__getDiarys());
  }, []);
  return (
    <DiaryDiv>
      <Diaryborder>
        {diarys.map((item) => {
          return <Diarys key={item.id} diary={item} />;
        })}
      </Diaryborder>
    </DiaryDiv>
  );
};

get 요청을 통해 데이터 값을 가져오고 Diary.jsx에서 역시 dipatch를 통해 getDiarys를 가져오자.

그 후에 Diarys 안에 diary.date와 title, content를 불러오면 끝이다.

 

이제 홈페이지를 보면 성공적으로 불러오는 것을 확인할 수 있다.

다음은 수정, 삭제를 구현해보자.

반응형