컴포넌트간 연결 없이 전역에서 상태를 관리할 수 있게 해주는 JS 라이브러리
1. Action
어떤 액션을 취할 것인지 정의해놓은 객체
2. Dispatch
Action -> Reducer 전달해주는 함수
3. Reducer
Dispatch로부터 받은 Action 객체의 type 값에 따라서 상태를 변경시키는 함수
4. Store
상태가 관리되는 오직 하나뿐인 저장소의 역할
Redux앱의 state가 저장되어 있는 공간
1. 설치
npm install redux react-redux
2. import
react-redux 기능들 import
import {Provider, useSelector, useDispatch, connect} from 'react-redux'
3. createStore
저장소 store 생성
반드시 reducer가 인자로 들어가야함
import { createStore } from 'redux';
const store = createStore('리듀서 함수가 들어옴')
4. reducer
store안의 state를 어떻게 변경할지에 대한 함수
두개의 매개변수를 가짐 (현재state값, state를 어떻게 바꿀 것인지 action)
각각 state값을 불변하게 관리해야하기 때문에 새로운 state를 만들어서 관리
fuction reducer(curState, action) {
// curState값이 없을 경우에는 기본값을 return 해주면 됨
if (curState === undefined){
return {
number : 1
}
const newState = {...curState}
if (action.type === 'PLUS'){
newState.number++;
}
return newState
5. Provider state 필요한 컴포넌트 감싸기
<Provider store={store}>
state 사용할 컴포넌트들
</Provider>
6. useSelector로 state를 변수로 관리
useSelector는 매개변수로 state가 들어오면서 state의 value를 리턴하는 함수를 가진다
function Left3(props) {
function f(state) {
return state.number;
}
const number = useSelector(f);
//const number = useSelector((state) => {return state.number})
return (
<div>
<h1>Left3 : {number}</h1>
</div>
);
}
7. dispatch로 action을 reducer 함수에 전달
// 컴포넌트 내부에 작성
function Right3(props) {
const dispatch = useDispatch();
return (
<div>
<h1>Right3</h1>
<button onClick={() => {
dispatch({ type: 'PLUS'})
}}> + </button>
</div>
);
}
right3 컴포넌트에서 left3 state를 변경할 수 있는 코드
import React, { useState } from "react";
import "./style.css";
import { Provider, useSelector, useDispatch } from "react-redux";
import { createStore } from "redux";
function reducer(curState, action) {
if (curState === undefined) {
return {
number: 1,
};
}
const newState = { ...curState };
if (action.type === 'PLUS'){
newState.number++;
}
return newState;
}
const store = createStore(reducer);
export default function App() {
return (
<div id="container">
<h1>Root</h1>
<div id="grid">
<Provider store={store}>
<Left1></Left1>
<Right1></Right1>
</Provider>
</div>
</div>
);
}
function Left1(props) {
return (
<div>
<h1>Left1</h1>
<Left2></Left2>
</div>
);
}
function Left2(props) {
return (
<div>
<h1>Left2</h1>
<Left3></Left3>
</div>
);
}
function Left3(props) {
function f(state) {
return state.number;
}
const number = useSelector(f);
//const number = useSelector((state) => {return state.number})
return (
<div>
<h1>Left3 : {number}</h1>
</div>
);
}
function Right1(props) {
return (
<div>
<h1>Right1</h1>
<Right2></Right2>
</div>
);
}
function Right2(props) {
return (
<div>
<h1>Right2</h1>
<Right3></Right3>
</div>
);
}
function Right3(props) {
const dispatch = useDispatch();
return (
<div>
<h1>Right3</h1>
<button onClick={() => {
dispatch({ type: 'PLUS'})
}}> + </button>
</div>
);
}