React Router를 이용한 라우팅(Switch, Router 등)
Redux CreateStore로 Store 생성하기
Redux combineReducers로 여러 Reducer 하나로 묶기
함수형 컴포넌트에서 Redux Store를 연결하는 방법(Provider)
클래스형 컴포넌트에서 Redux Store를 연결하는 방법(Connect)
함수형 컴포넌트에서 Redux를 이용한 전역 상태관리
yarn add react-router-dom
index.js
에 import 및 컴포넌트 <BrowserRouter>
처리
import { BrowserRouter } from "react-router-dom";
ReactDOM.render()
내 컴포넌트들을 <BrowserRouter>
로 감싼다.
return
부분에 <Route path="/"</Route>
Route할 컴포넌트들 추가
path가 지정되지 않은 비정상 접근 같은 경우 <Route></Route>
를 <Switch></Switch>
로 감싸고 path
prop이 없는 <Route></Route>
를 추가하면 됨.
아래 코드를 configStore.js
파일로 생성하되, src/redux/modules 디렉토리에 생성
import { createStore, combineReducers } from "redux";
import quiz from "./modules/quiz";
import rank from "./modules/rank";
import { createBrowserHistory } from "history";
export const history = createBrowserHistory();
const rootReducer = combineReducers({ quiz, rank });
const store = createStore(rootReducer);
export default store;
index.js
에 추가// store를 컴포넌트에 연결해주는 역할
import { Provider } from "react-redux";
// 앞에서 생성한 store 불러오기
import store from "./redux/configStore";
render()
부분에 모든 컴포넌트를 <Provider store={store}></Provider>
로 감싼다.아래 코드를 Redux를 사용할 js파일에 추가
// 리덕스 스토어와 연결하기 위해 connect import
import {connect} from 'react-redux';
// 리덕스 모듈에서 (bucket 이라는 모듈을 가정) 액션 생성 함수 두개 import
import {loadBucket, createBucket} from './redux/modules/bucket';
// 스토어가 가진 상태값을 props로 받아오기 위한 함수
const mapStateToProps = (state) => ({
bucket_list: state.bucket.list,
});
// 값을 변화시키기 위한 액션 생성 함수를 props로 받아오기 위한 함수
const mapDispatchToProps = (dispatch) => ({
load: () => {
dispatch(loadBucket());
},
create: (new_item) => {
dispatch(createBucket(new_item));
}
});
아래 코드를 Redux를 사용할 js파일에 추가
// import
import {useSelector, useDispatch} from 'react-redux';
// configStore.js 파일에서 bucket이라는 이름으로 정의된(bucket이라는 js파일) 객체에서 list 객체 불러와서 bucket_list 변수에 저장
const bucket_list = useSelector(state => state.bucket.list);
Detail.js
import React from "react";
// redux hook 불러오기
import { useSelector, useDispatch } from "react-redux";
// 직접 생성한 버킷 삭제 액션 생성 함수 불러오기
import {deleteBucket} from "./redux/modules/bucket";
const Detail = (props) => {
// useDispatch()는 이런 식으로 선언해주지 않고 직접 사용하면 오류 발생!
const dispatch = useDispatch();
// 스토어에서 상태값 가져오기
const bucket_list = useSelector((state) => state.bucket.list);
// url 파라미터에서 인덱스 가져오기
let bucket_index = parseInt(props.match.params.index);
console.log(props);
return (
<div>
<h1>{bucket_list[bucket_index]}</h1>
<button onClick={() => {
dispatch(deleteBucket(bucket_index));
props.history.goBack();
}}>삭제하기</button>
</div>
);
};
export default Detail;
bucket.js
: 액션, 액션 생성 함수, 리듀서가 있는 파일 (DELETE 키워드를 보면 됨)
// Actions
const LOAD = "bucket/LOAD";
const CREATE = "bucket/CREATE";
const DELETE = "bucket/DELETE";
const initialState = {
list: ["영화관 가기", "매일 책읽기", "수영 배우기"],
};
// Action Creators
export const loadBucket = (bucket) => {
return { type: LOAD, bucket };
};
export const createBucket = (bucket) => {
return { type: CREATE, bucket };
};
export const deleteBucket = (bucket) => {
return { type: DELETE, bucket };
};
// Reducer
export default function reducer(state = initialState, action) {
console.log(action);
switch (action.type) {
// do reducer stuff
case "bucket/LOAD":
return state;
case "bucket/CREATE":
console.log(state, action);
const new_bucket_list = [...state.list, action.bucket];
return { list: new_bucket_list };
case "bucket/DELETE":
const bucket_list = state.list.filter((l, idx) => {
if(idx !== action.bucket){
return l;
}
});
return {list: bucket_list};
default:
return state;
}
}