리액트 기초반 3주차 - 2

26925 단어 ReactReact

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>
    );
}

좋은 웹페이지 즐겨찾기