[React + Redux] study 6주차 (1) - React에 Redux 적용하기

newsilver·2022년 2월 26일
1

react-study

목록 보기
6/9
post-thumbnail

5주차 과제에서 useReducer로 상태 변경을 시도했다가 객체 속성에 직접 접근하게 되었고, Recoil도 적용하는데 실패했다.
redux 사용법을 익히기 위해 5주차 과제에 적용하다보니 이러한 문제점들을 해결하게 되었다.

Redux

설치

$ npm install redux react-redux

action type, action creator 생성

src/reducers/loginReducer.js

// action type
const LOGIN = "LOGINREDUCER/LOGIN";
const LOGOUT = "LOGINREDUCER/LOGOUT";

// action creators
const login = userName => ({ type: LOGIN, userName});
const logout = () => ({ type: LOGOUT, userName:""});

Reducer 생성

action에 따라 reducer를 실행하여 상태를 변경한다.
src/reducers/loginReducer.js

const visitor = {
  isLogined: false,
  userName: ""
}

function loginReducer(state = visitor, action) {
  // 초기 상태로 visitor 지정
  switch (action.type) {
    case LOGIN:
      return {
        ...state,
        isLogined: true,
        userName: action.userName
      };
    case LOGOUT:
      return {
        isLogined: false,
        userName: ""
      }
    default:
      return state;
  }
}

export { loginReducer, login, LOGIN, logout, LOGOUT }

각 컨포넌트별로 리듀서를 작성하거나, 또는 프로젝트 마다 특정 조건에 따라 분리하여 리듀서를 작성한다. 그 후 combineReducers()로 리듀서를 통합한다.

combineReducer 생성

src/reducers/index.js

import { combineReducers } from "redux";
import { loginReducer } from './loginReducer';

const rootReducer = combineReducers({
  loginReducer
});

export default rootReducer;

store 생성

리덕스 데브툴 설치

$ npm i -S redux-devtools-extension

createStore로 store 생성

index.js

// app에 store 넣고, 만든 reducer 반영
import { createStore, applyMiddleware, compose } from "redux";

import { Provider } from "react-redux";
import logger from "redux-logger";
import { composeWithDevTools } from "redux-devtools-extension";

import rootReducer from './reducers';

// 배포 레벨에서는 리덕스 발동시 찍히는 logger를 사용하지 않습니다.
const enhancer =
  process.env.NODE_ENV === "production"
    ? compose(applyMiddleware())
    : composeWithDevTools(applyMiddleware(logger));

// 위에서 만든 reducer를 스토어 만들때 넣어줍니다
const store = createStore(rootReducer, enhancer);

ReactDOM.render(
  <Provider store={store}>
  <App />
  </Provider>,
  document.getElementById('root')
);

Reducer 적용

src/Components/LoginForm.js

// redux 사용하기
import { useSelector, useDispatch } from "react-redux";
import { login, logout } from '../reducers/loginReducer';

import { useState, useEffect } from 'react';
import { useSetRecoilState } from 'recoil';

import CommentsForm from './CommentsForm';
import { userNameState } from '../State/userNameState';

import styles from './LoginForm.module.css';

function LoginForm() {
  const [input, setInput] = useState("");
  // redux 사용하기
  // dispatch를 사용하기 위한 준비
  const dispatch = useDispatch();

  // store에 접근하여 state 가져오기
  const { userName } = useSelector(state => state.loginReducer);
  const { isLogined } = useSelector(state => state.loginReducer);
  // reselect 적용해보기.

  const loginFunc = () => {
    // store에 있는 state 바꾸는 함수 실행
    dispatch(login(input));
  }

  const logoutFunc = () => {
    dispatch(logout());
  }

  const setUserName = useSetRecoilState(userNameState);
  const loginText = isLogined ? "LOGOUT" : "LOGIN";
  const getUserName = JSON.parse(window.localStorage.getItem("user-name"));

  function onChangeInputHandler(e) {
    const text = e.target.value;
    setInput(text);
  }

  function onClickSubmitHandler(e) {
    e.preventDefault();
    if (!isLogined){
      window.localStorage.setItem("user-name", JSON.stringify(input));
      loginFunc();
      setUserName(getUserName);
      return;
    }
    localStorage.removeItem("user-name");
    logoutFunc();
  }

  const inputText = <input type="text" onChange={onChangeInputHandler}/>;

  return (
    <div>
    <form>
      {isLogined ? <h2>{userName}</h2> : inputText}
      <button 
        type="button" 
        onClick={onClickSubmitHandler}>
        {loginText}
      </button>
    </form>
    <CommentsForm isLogined={isLogined} userName={userName}/>
    </div>
  )
}

export default LoginForm;
profile
이게 왜 🐷

0개의 댓글