리액트 기초반 3주차 - 2
22년 4월 5일(화)
[스파르타코딩클럽] 리액트 기초반 - 3주차
◎ 상태관리
- 상태관리의 필요성
- 일반적으로 데이터는 부모에서 자식에게 준다. (자식에서 부모에게 주면 무한 랜더링이 걸릴 수 있기 때문에)
- 부모와 자식의 관계가 중첩된다면, 해당 Component에게는 필요없는 데이터를 계속 들고 있다가 자식에게 주어야 하는 경우가 생긴다. (Data Drilling)
- 부모 자식 관계 선에 없는 경우에는 서로 데이터를 주지 못하는 경우가 발생한다.
->따라서 공용으로 사용할 수 있는 Data 저장소가 필요하다.
- 상태관리의 흐름도
- (1) 리덕스 Store를 Component에 연결한다.
- (2) Component에서 상태 변화가 필요할 때 Action을 부른다.
- (3) Reducer를 통해서 새로운 상태 값을 만들고,
- (4) 새 상태값을 Store에 저장한다.
- (5) Component는 새로운 상태값을 받아온다. (props를 통해 받아오니까, 다시 랜더링 됨)
◎ 리덕스(Redux)
-
아주 흔히 사용하는 상태관리 라이브러리 / 전역 상태관리를 편히 할 수 있음
리덕스는 데이터를 한 군데 몰아넣고, 여기저기에서 꺼내볼 수 있게 해줌 -
패키지 설치하기
yarn add redux react-redux
-
리덕스 개념과 용어
-
State : Redux에서 저장하고 있는 상태값 / dictionary의 형태로 값을 보관
-
Action : 상태의 변화가 필요할 때(=가지고 있는 데이터를 변경할 때), 발생하는 것
-
ActionCreater : 액션 생성 함수, 액션을 만들기 위해 사용
-
Reducer : 리덕스에 저장된 상태(=데이터)를 변경하는 함수
우리가 액션 생성 함수를 부르고 → 액션을 만들면 → 리듀서가 현재 상태(=데이터)와 액션 객체를 받아서 → 새로운 데이터를 만들고 → 리턴해줌 -
Store : 프로젝트에 리덕스를 적용하기 위해 만드는 것
스토어에는 리듀서, 현재 애플리케이션 상태, 리덕스에서 값을 가져오고 액션을 호출하기 위한 몇 가지 내장 함수가 포함되어 있음
생김새는 딕셔너리 혹은 json처럼 생겼음 -
dispatch : 액션을 발생 시키는 역할
-
-
Redux의 특징
-
Store는 1개만 사용
리덕스는 단일 스토어 규칙을 따른다. -
Store의 state는 오직 action으로만 변경시킬 수 있다.
데이터가 마구잡이로 변하지 않도록 불변성을 유지해주기 위함 -
어떤 요청이 와도 리듀서는 같은 동작을 해야한다
파라미터 외의 값의 의존 X, 파라미터가 같으면 항상 같은 값을 반환, 이전 상태는 수정X
-
◎ 리덕스(Redux) 사용해보기
- 덕스(ducks) 구조 사용
- 덕스 구조: 기능으로 묶어 작성합니다. (action, actionCreator, reducer를 한 파일에 넣음.)
- 일반적으로는 모양새대로 action, actionCreator, reducer를 분리해서 작성함
// src > redux > modules > bucket.js
//Actions
// const LOAD = 'bucket/LOAD'; // 서버에서 가지고 올때 사용
const CREATE = 'bucket/CREATE'; // 추가하기 기능
// const UPDATE = 'bucket/UPDATE';
const REMOVE = 'bucket/REMOVE';
// 초기값 설정
const initialState = {
list: ["영화관 가기", "매일 책읽기", "수영 배우기","현우 재수시키기"],
};
// Action Creators
export const createBucket = (bucket) => {
return {type: CREATE, bucket};
}
export const removeBucket = (bucket) => {
return {type: REMOVE, bucket};
}
// Reducer
export default function reducer(state = initialState, action = {}) {
switch (action.type) {
// do reducer stuff
// return state;
case "bucket/CREATE":
const new_bucket_list = [...state.list, action.bucket];
return { list: new_bucket_list };
case "bucket/REMOVE":
const remove_bucket_list = state.list.filter((list_item)=> {
return list_item !== action.bucket
})
return {list: remove_bucket_list };
default:
return state;
}
}
// src > redux > configStore.js
import {createStore, combineReducers} from "redux";
import bucket from "./modules/bucket";
// {} 안에 사용할 모든 Redux들을 넣어 Reducer들을 합침
const rootReducer = combineReducers({bucket});
const store = createStore(rootReducer);
export default store;
- state 불러오기 예제
// src > Bucket.js
import React from "react";
import { useHistory } from "react-router-dom";
import {useSelector} from "react-redux";
const BucketList = (props) => {
// react-redux의 useSelector를 이용해 현재 state 값을 불어옴
const data = useSelector((state) => state.bucket.list); // ["영화관 가기", "매일 책읽기", "수영 배우기","현우 재수시키기"]
const my_lists = data
let history = useHistory();
return (
<ListStyle>
{
my_lists.map((list, index) => {
return (
<ItemStyle className="list_item" key={index} onClick={() => {history.push("/detail/"+index);}}>
{list}
</ItemStyle>
);
})
}
</ListStyle>
);
};
- state 변경하기 예제
// src > Detail.js
import React from "react";
import {useParams, useHistory} from "react-router-dom";
import {useSelector, useDispatch} from "react-redux";
import { removeBucket } from "./redux/modules/bucket";
const Detail = () => {
const history = useHistory();
const dispatch = useDispatch();
const params = useParams();
const BucketList = useSelector((state) => state.bucket.list);
console.log(BucketList[params.index])
const DeleteList = () => {
// dispatch( ActionCrearter ) 형식으로 데이터를 바꿈
// 아래 경우는 removeBucket을 이용해 bucket 데이터를 수정
dispatch(removeBucket(BucketList[params.index]))
history.goBack();
}
return (
<div>
<h1>{BucketList[params.index]}</h1>
<button onClick={DeleteList}>삭제하기</button>
</div>
)
}
export default Detail
// src > App.js의 일부
import React from "react";
import {Route, Switch} from "react-router-dom";
import { useDispatch } from "react-redux";
import { createBucket } from "./redux/modules/bucket";
import BucketList from "./BucketList";
import Detail from "./Detail";
import NotFound from "./NotFound";
function App() {
const dispatch = useDispatch();
const text = React.useRef(null);
const addBucketList = () => {
// dispatch( ActionCrearter ) 형식으로 데이터를 바꿈
// setList([ ...list, text.current.value]);
dispatch(createBucket(text.current.value))
}
return (
<div className="App">
<Input>
<input type="text" ref={text}/>
<button onClick={addBucketList}>추가하기</button>
</Input>
</div>
);
}
Author And Source
이 문제에 관하여(리액트 기초반 3주차 - 2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gwichanlee/리액트-기초반-3주차-2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)