1. 덕스(ducks)구조
보통은 리덕스를 사용할때는 모양대로 구분해서 코드를 작성해준다.
(액션은 액션대로, 액션생성함수는 액션생성함수끼리, 리듀서는 리듀서끼리 작성)
덕스구조는 모양새대로 묶는것이 아닌 기능대로 묶어주는것을 말한다.
리덕스 기본형태를 아래 깃허브를 참고하자.
https://github.com/erikras/ducks-modular-redux
// widgets.js // Actions const LOAD = 'my-app/widgets/LOAD'; const CREATE = 'my-app/widgets/CREATE'; const UPDATE = 'my-app/widgets/UPDATE'; const REMOVE = 'my-app/widgets/REMOVE'; // Reducer export default function reducer(state = {}, action = {}) { switch (action.type) { // do reducer stuff default: return state; } } // Action Creators export function loadWidgets() { return { type: LOAD }; } export function createWidget(widget) { return { type: CREATE, widget }; } export function updateWidget(widget) { return { type: UPDATE, widget }; } export function removeWidget(widget) { return { type: REMOVE, widget }; } // side effects, only as applicable // e.g. thunks, epics, etc export function getWidget () { return dispatch => get('/widget').then(widget => dispatch(updateWidget(widget))) } |
기본형태는 외울필요 없이 구조가 어떻게 생겼는지정도만 파악해두고 가져다가 쓰자!
자주보고 사용하다보면은 자연스럽게 익혀질것이다!
2. bucke_list 에 리덕스를 사용해보자.
우선, src 폴더 아래 redux 폴더 그 아래 modules 폴더를 만들어 bucket.js 를 만들자!
다음과 같은 과정으로 버킷리스트 항목을 리덕스에서 관리하도록 변경해보자.(작업 순서를 이해하면서 복습하자.)
1. Action : 액션은 처음 로드되었을때, 버킷리스트 항목을 추가했을때 발생한다.
const LOAD = 'bucket/LOAD'; const CREATE = 'bucket/CREATE'; |
2. initialState : 초기 상태값을 만들어준다. (= 기본값)
const initialState = { list: ["영화관 가기", "매일 책읽기", "수영 배우기"], }; |
3. Action Creactor : 액션 생성함수
export const loadBucket = (bucket) => { return { type: LOAD, bucket }; } export const createBucket = (bucket) => { return {type: CREATE, bucket}; } |
4. Reducer : load할때는 기본값을 뿌려주면되고, create 할때는 새로 받아온 값을 기본값에 더해서 리턴
(action으로 넘어오는 값은 text)
export default function reducer(state = initialState, action = {}) { switch (action.type) { // do reducer stuff case "bucket/LOAD": return state; case "bucket/CREATE": const new_bucket_list = [...state.list, action.bucket]; return { list: new_bucket_list }; default: return state; } } |
5. Store : redux 폴더 하위에 configStore.js 파일을 만들어서 스토어를 만들어보자.
//configStore.js import { createStore, combineReducers } from "redux"; import bucket from './modules/bucket'; import { createBrowserHistory } from "history"; // 브라우저 히스토리를 만들어준다. export const history = createBrowserHistory(); // root 리듀서를 만들어준다. // 나중에 리듀서를 여러개 만들게 되면 여기에 하나씩 추가해주면된다. const rootReducer = combineReducers({ bucket }); // 스토어를 만듭니다. const store = createStore(rootReducer); export default store; |
3. 리덕스와 컴포넌트 연결하기
index.js 에 필요한 작업을 하면되며, 스토어를 불러오고 버킷리스트에 주입하면 끝!
4. 클래스형 컴포넌트에서 리덕스 데이터 사용하기
1) 리덕스 모듈과 connect 함수를 불러온다.
import {connect} from 'react-redux';
import {loadBucket, createBucket} from './redux/modules/bucket';
2) 상태값을 가져오는 함수와 액션 생성 함수를 부르는 함수를 만들어준다.
// 이 함수는 스토어가 가진 상태값을 props로 받아오기 위한 함수. const mapStateToProps = (state) => ({ bucket_list: state.bucket.list, }); // 이 함수는 값을 변화시키기 위한 액션 생성 함수를 props로 받아오기 위한 함수. const mapDispatchToProps = (dispatch) => ({ load: () => { dispatch(loadBucket()); }, create: (new_item) => { dispatch(createBucket(new_item)); } }); |
3) connect로 컴포넌트와 스토어를 엮어준다
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(App));
4) 콘솔에 this.props를 찍어봅니다. (스토어에 있는 값이 잘 나왔는지 확인)
componentDidMount() {
console.log(this.props);
}
5) this.state에 있는 list를 지우고 스토어에 있는 값으로 바꿔보자.
6) setState를 this.props.create로 바꿔보자.
addBucketList = () => {
const new_item = this.text.current.value;
this.props.create(new_item);
};
5. 함수형 컴포넌트 리덕스 데이터 사용하기
- 리덕스에도 리액트처럼 훅을 사용할 수 있다. 훅을 사용해서 액션 생성 함수도 불러오고, 스토어에 있는 값도 가져올 수 있다.
1) BucketList.js 에 useSelector() 적용하기
// redux hook을 불러온다 import {useDispatch, useSelector} from 'react-redux'; const BucketList = (props) => { // 버킷리스트를 리덕스 훅으로 가져오기 const bucket_list = useSelector(state => state.bucket.list); console.log(bucket_list); |
2) App.js에 몇번째 상세페이지인지 알아야 하므로 URL 파라미터를 적용해보자.
<Switch> <Route path="/" exact render={(props) => <BucketList history={props.history} />} /> <Route path="/detail/:index" render={(props) => <Detail match={props.match} history={props.history} />} /> // match 객체는 해당 컴포넌트가 어떤 라우트에 매치되어 있는지에 대한 정보가 있고, 파라메터 정보를 params 속성으로 지닌다 <Route render={(props) => <NotFound history={props.history} />} /> </Switch> |
3) BucketList.js 에 onClick 함수에 배열의몇번째 항목을 눌렀는지 알려주자(url 파라미터로 넘겨주면된다.)
{bucket_list.map((list, index) => { return ( <ItemStyle className="list_item" key={index} onClick={() => { // 배열의 몇번째 항목을 눌렀는 지, url 파라미터로 넘겨줍니다. props.history.push("/detail/"+index); }} > {list} </ItemStyle> ); })} </ListStyle> ); }; |
4) Detail.js (상세페이지)에서 버킷리스트 내용을 띄워보자.
// 리액트 패키지를 불러온다. import React from "react"; // redux hook을 불러온다. import { useDispatch, useSelector } from "react-redux"; const Detail = (props) => { // 스토어에서 상태값 가져오기 const bucket_list = useSelector((state) => state.bucket.list); // url 파라미터에서 인덱스 가져오기 let bucket_index = parseInt(props.match.params.index); return <h1>{bucket_list[bucket_index]}</h1>; }; export default Detail; |
※ 버킷리스트 데이터를 삭제해보기!
1. Detail.js 에 삭제버튼 만들고, 액션생성함수 만들기
... return ( <div> <h1>{bucket_list[bucket_index]}</h1> <button onClick={() => { // dispatch(); <- 괄호안에는 액션 생성 함수가 들어가면된다. dispatch(deleteBucket(bucket_index)); // 삭제 후 그 페이지에 두지말고 뒤로가기를 통해 원래 화면으로 넘어가주게 한다. 사용성을 위해 props.history.goBack(); }}>삭제하기</button> </div> ); }; export default Detail; |
2. bucket.js 에 액션생성함수, 액션, 리듀서를 만들어준다.
- Action
const DELETE = "bucket/DELETE";
- Action Creator
export const deleteBucket = (bucket) => {
return { type: DELETE, bucket };
};
- Reducer
case "bucket/DELETE":
const bucket_list = state.list.filter((l, idx) => {
if(idx !== action.bucket){
return l;
}
});
return {list: bucket_list};
이렇게 하면은 정상적으로 삭제되고 버킷리스트 목록으로 넘어가는걸 볼 수 있다.
우선은 어떻게 동작하는지 원리를 파악하는데 중점을 두자!
'내마음대로만들어보자 > React' 카테고리의 다른 글
React - 프로그래스바 적용하기 (0) | 2021.07.28 |
---|---|
keyframes - transition , animation (0) | 2021.07.27 |
리덕스란? - 리덕스를 통한 상태관리 (0) | 2021.07.26 |
잘못된 주소 처리 - NotFound (라우팅) (0) | 2021.07.26 |
라우팅이란 (0) | 2021.07.26 |