Spring

리덕스 Redux. 구조분해 연산자.

wintertreey 2024. 8. 1. 18:03

 

"" (문자열 리터럴)과 {} (중괄호)

 <input type="text" value="0" readOnly></input>

 

  • 문자열 리터럴 "": value="0"은 입력 필드의 값을 "0"으로 설정.
  • 값이 하드코딩됨: 이 경우, value 속성은 항상 문자열 "0"을 가진다. React 상태나 props에 의존하지 않으며, 이 값은 고정되어 있다.

만약 value={}로 적는다면

  • 중괄호 {}: {}를 사용하면 JavaScript 표현식을 JSX 내에서 평가하게된다. 예를들어 value={this.props.number}는 this.props.number라는 JavaScript 표현식을 평가하여 value 속성에 설정해준다.
  • 동적 값: value 속성에 설정된 값이 컴포넌트의 상태나 props에 따라 동적으로 변할 수 있다. 예를 들어, this.props.number의 값이 변하면 입력 필드의 값도 자동으로 업데이트된다.
  • 동적 렌더링: React의 상태나 props에 따라 입력 필드의 값이 변경될 수 있어, 사용자에게 표시되는 값이 컴포넌트의 상태나 외부 입력에 따라 달라질 수 있다.

 

import React, {Component} from "react";
import store from "../store";

export default class AddNumber extends Component{
    state = {size:1}

    render(){
        return(
            <div>
                <h3>Add Number</h3>
                <input type="button" value="+" onClick={function(){ //+버튼클릭시 함수수행.
                    this.props.onClick(this.state.size); //부모의 온클릭메소드를 호출
                }.bind(this)}></input>

                <input type="text" value={this.state.size} onChange={function(e){
                    this.setState({size:Number(e.target.value)});
                }.bind(this)}></input>
            </div>
        );
    }
}

 

+버튼 클릭시 size 값이 상위 컴포넌트로 전달될 수 있게 onClick을 구현.
props로 전달받은 onClick 함수를 호출. 현 컴포넌트의 state인 size값을 전달.
onClick: addnumber함수 이벤트핸들러.

this.props.onClick: addnumbersuper함수.

import React, {Component} from "react";
import AddNumber from "./AddNumber";

export default class AddNumberSuper extends Component{
    render(){
        return(
            <div id="super">
                <h2>Add Number Super</h2> {/* onClick이라는 속성*/}
                <AddNumber onClick={function(siz){
                    this.props.onClick(siz);
                }.bind(this)}></AddNumber
            </div>
        );
    }
}

 

addnumber의 props로 매개변수가 size인 함수를 전달한다.
이 함수는 addnumber의 +버튼을 클릭했을때 addnumber의 state.size값을 호출.
이 size값을 다시 상위컴포넌트 App으로 전달하려면
상위 컴포넌트로부터 전달받은 props의 onClick함수를 호출해서 size 값을 전달해야한다.

App.js

import './App.css';
import React, {Component} from 'react';
import AddNumberSuper from './mydir/AddNumberSuper';
import ShowNumberSuper from './mydir/showNumberSuper';


class App extends Component {
  state = {number:0}

  render(){
    return (
      <div className="App">
       <h1>Main</h1>
       <AddNumberSuper onClick={function(ss){
        this.setState({number:this.state.number + ss})
       }.bind(this)}></AddNumberSuper>
       App의 number : {this.state.number}
       <ShowNumberSuper numb={this.state.number}></ShowNumberSuper>

      </div>
    );
  }
}

export default App;

 

App소유 state변수 number + size(=addnumbersuper가 전달한 값) */}

onclick이라는 props으로 끌어올려 받음. 
 App이 받아 이걸 상단 number: {}로 찍어보았다.
이제 numb라는 props로 다시 내려보내자.

import React, {Component} from "react";
import ShowNumber from "./showNumber";

export default class ShowNumberSuper extends Component{
    render(){
        return(
            <div id="super">
                <h2>ShowNumber Super</h2>
                ShowNumber Super의 numb: {this.props.numb}
                <ShowNumber num={this.props.numb}></ShowNumber>
            </div>
        );
    }
}

 

import React, {Component} from "react";
import store from "../store";

export default class ShowNumber extends Component{
    state= {number:store.getState().number}

    constructor(props){
        super(props);

        store.subscribe(function(){
            this.setState({number:store.getState().number});
        }.bind(this));
    }
    render(){
        return(
            <div>
                <h3>Show Number</h3>
                <input type="text" value={this.props.num} readOnly></input>
            </div>
        );
    }
}

 

 

 


 

앞선 연습은 리덕스없이 수행하였다.

리덕스를 이용한다면, 보다 쉽고 편하게 값을 넘기고 받을 수 있다. 그렇다면 리덕스란 무엇일까?

 

 

Redux란

상태 관리 라이브러리로 Component별로 props/state를 바꿔주는 복잡한 관계를 redux 하나로 외부에서 state들을 공용으로 관리하여 가져다 쓸 수 있다.

 

리덕스가 없다면, 앞선 실습처럼(without 그림처럼) 스텝바이스텝 올려주어야한다.

 

 

Redux 흐름


View에서 action 수행 → Dispatch 을 반드시 거쳐서 Store로 전달 → action에 해당되는 Callback 수행 → state 업데이트 → 업데이트 된 State를 View에서 받아서 출력

 

 

1. State(상태)

State란 React Component 내에서 사용되는 데이터 집합을 말하며 이 상태 정보를 가지고 컴포넌트의 속성을 바꾸거나 어떤 event가 일어났을 경우 상태 값을 변경하여 Component를 변경된 상태로 렌더링할 수 있다. 

이런 State를 변경하는 것이 (Action)이며 Action과 Store를 연결해주는 스토어 관리자가 (Dispatcher)다.

 

2. Action

Action은 상태 변경을 일으키는 이벤트에 대한 정적 정보다.

Action은 Reducer가 구분할 수 있도록 액션 타입과 데이터를 가진 객체 형식이다. 아래와 같이 reducer에 있는 액션 타입들을 받아와 외부에서도 action을 일으킬 수 있도록 type과 payload(Data)를 받아 새로운 State로 설정할 수 있도록 Action들을 선언한다.상태는 반드시 Action을 통해서만 바꿀 수 있으며 그 외의 상황에서는 state를 읽는 것만 가능하다.

 

3. Reducer

Reducer는 Action이 일으킨 상태 변화를 Action Type에 따라 Data를 받고 이전 State와 비교하여 새로운 State를 내보낸다.

Action Type을 선언할때는 같은 타입의 액션이 있을 수 있으므로 액션 앞에 Reducer명을 붙여주거나 해서 구분한다. Reducer 내에서는 switch문으로 Action 타입에 따라 State를 비교하고 바꿔준다.

 

4. Store

Store는 State들을 관리하는 저장소다.

 

 

 


 

구조 분해 연산자 (Spread Operator)

// 액션의 타입이 'INCREMENT'일 경우 상태를 업데이트합니다.
if (action.type === 'INCREMENT') {
    // 구조 분해 연산자를 사용하여 기존 상태를 복사하고, number 속성만 변경합니다.
    return {
        ...state, // 기존 상태의 모든 속성을 복사합니다.
        number: state.number + action.size // number 속성만 업데이트합니다.
    };
}

 

구조 분해 연산자는 JavaScript의 문법 중 하나로, 배열이나 객체의 내용을 새로운 배열이나 객체로 복사할 때 사용한다. 주로 다음과 같은 방식으로 사용된다.

  • 배열 복사: [...array] — 기존 배열의 요소를 새로운 배열로 복사
  • 객체 복사: {...object} — 기존 객체의 속성을 새로운 객체로 복사

 

상세 설명

1. if (action.type === 'INCREMENT')

 

이 조건문은 액션의 타입이 'INCREMENT'인지 확인한다. 만약 조건이 참이라면, 상태를 업데이트하는 로직이 실행된다.

 

 

2. return { ...state, number: state.number + action.size }

 

구조 분해 연산자 ...state:

현재 상태(state)의 모든 속성을 복사하여 새로운 객체를 만듭니다. 이 방식으로 기존의 상태를 보존하면서 일부 속성만 변경할 수 있습니다.

 

number: state.number + action.size:

상태의 number 속성만 업데이트한다. 기존의 number 값에 action.size를 더하여 새로운 number 값을 설정.

action.size는 액션에 포함된 데이터를 참조하며, 이 값을 number에 추가한다.

 

예시

  • 초기 상태: { number: 10 }
  • 액션: { type: 'INCREMENT', size: 5 }

업데이트 과정:

  1. action.type이 'INCREMENT'이므로 조건이 참입니다.
  2. 구조 분해 연산자 ...state를 사용하여 기존 상태 객체 { number: 10 }을 복사합니다.
  3. number 속성만 state.number + action.size로 업데이트합니다. 즉, 10 + 5 = 15가 됩니다.
  4. 최종적으로 { number: 15 }가 반환되어 새로운 상태로 설정됩니다.

요약

  • 구조 분해 연산자 (...): 객체나 배열의 내용을 새로운 객체나 배열로 복사할 때 사용됩니다.
  • 상태 업데이트: 기존 상태를 복사하고, 특정 속성만 변경하여 새로운 상태 객체를 생성합니다.

 

리덕스 설치( 해당 프로젝트 별로 설치한다. )

npm install redux

 

 

 

import { legacy_createStore as createStore } from "redux";


export default createStore(function(state, action){

    if(state === undefined){
        return {number:0} // number 초기화
    }
    if(action.type === 'INCREMENT'){ // 액션의 타입이 'INCREMENT'일 경우 상태를 업데이트

        return {...state, // 기존 상태의 모든 속성을 복사.
            number:state.number + action.size} //// number 속성만 업데이트.
    }
    return state;
},window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ &&
window.__REDUX_DEVTOOLS_EXTENSION__())

 

createStore는 인자가 2개. 리듀서함수,리덕스dv툴스지정 
리듀서함수

어플리케이션 상태를 변환하는 함수. A상태>B상태. state와 action을 전달받아 상태변환 후 반환해준다.하는일

1) action type분석. 2) 이전상태>다음상태로 교체. 3) 다음상태 반환.

state: 데이터. action: 데이터에 가해지는 행위.

 

구조 분해 연산자를 사용하여 기존 상태를 복사하고, number 속성만 변경한다.

createStore 두번째 매개변수는 redux_devtools를 사용하기 위한 지정값.

 

 

import React, {Component} from "react";
import store from "../store";

export default class AddNumber extends Component{
    state = {size:1}

    render(){
        return(
            <div>
                <h3>Add Number</h3>
               
                {/* redux 사용 */}
                <input type="button" value="+" onClick={function(){
                   store.dispatch({type:'INCREMENT', size:this.state.size});
                }.bind(this)}></input>

                <input type="text" value={this.state.size} onChange={function(e){
                    this.setState({size:Number(e.target.value)});
                }.bind(this)}></input>
            </div>
        );
    }
}
import React, {Component} from "react";
import AddNumber from "./AddNumber";

export default class AddNumberSuper extends Component{
    render(){
        return(
            <div id="super">
                <h2>Add Number Super</h2> {/* onClick이라는 속성*/}
                <AddNumber></AddNumber>
            </div>
        );
    }
}
import React, {Component} from "react";
import store from "../store";

export default class ShowNumber extends Component{
    state= {number:store.getState().number}

    constructor(props){
        super(props);

        store.subscribe(function(){
            this.setState({number:store.getState().number});
        }.bind(this));
    }
    render(){
        return(
            <div>
                <h3>Show Number</h3>

                {/* redux 사용*/}
                <input type="text" value={this.state.number} readOnly></input>

            </div>
        );
    }
}

 

import React, {Component} from "react";
import AddNumber from "./AddNumber";

export default class AddNumberSuper extends Component{
    render(){
        return(
            <div id="super">
                <h2>Add Number Super</h2> {/* onClick이라는 속성*/}

                <AddNumber></AddNumber>
            </div>
        );
    }
}
import './App.css';
import React, {Component} from 'react';
import AddNumberSuper from './mydir/AddNumberSuper';
import ShowNumberSuper from './mydir/showNumberSuper';


class App extends Component {
  state = {number:0}

  render(){
    return (
      <div className="App">
       <h1>Main</h1>

      <AddNumberSuper></AddNumberSuper>
      <ShowNumberSuper></ShowNumberSuper>
      </div>
    );
  }
}

export default App;

 


 

 

 

https://medium.com/@heoh06/%EB%A6%AC%EC%95%A1%ED%8A%B8-redux%EC%99%80-%EC%82%AC%EC%9A%A9%EB%B2%95-731853fc3cd4

 

[리액트] Redux와 사용법

React 상태관리 라이브러리 Redux의 설명과 사용법

medium.com

https://chuun92.tistory.com/28

 

[React/Redux] Redux 사용법 (1) -State/Action/Reducer/Store

Redux란? 상태 관리 라이브러리로 Component별로 props/state를 바꿔주는 복잡한 관계를 redux 하나로 외부에서 state들을 공용으로 관리하여 가져다 쓸 수 있다. 1. State(상태) State란 React Component 내에서 사

chuun92.tistory.com

https://11001.tistory.com/189

 

React Redux Tookit 사용 방법

본 게시물에서는 Redux Toolkit 을 사용한 버전으로 예시를 들어보겠다. 리덕스를 훨씬 편한 방법으로 사용할 수 있는 확장팩이라고 생각하면 된다. Redux Toolkit | Redux Toolkit The official, opinionated, batteri

11001.tistory.com