wintertreey 님의 블로그
리덕스 Redux. 구조분해 연산자. 본문
"" (문자열 리터럴)과 {} (중괄호)
- 문자열 리터럴 "": 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 }
업데이트 과정:
- action.type이 'INCREMENT'이므로 조건이 참입니다.
- 구조 분해 연산자 ...state를 사용하여 기존 상태 객체 { number: 10 }을 복사합니다.
- number 속성만 state.number + action.size로 업데이트합니다. 즉, 10 + 5 = 15가 됩니다.
- 최종적으로 { 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
https://chuun92.tistory.com/28
'백엔드 > Spring' 카테고리의 다른 글
wmvc 연습. #{}와 ${}의 차이 (0) | 2024.08.01 |
---|---|
aspectJ pointcut 표현식 (0) | 2024.08.01 |
@MVC - MyBatis : 미니게시판 (1) | 2024.07.22 |
@MVC DB연동4 : Spring DATA JPA JpaRepository CRUD (2) | 2024.07.22 |
@MVC DB연동4 : Spring DATA JPA JpaRepository (0) | 2024.07.21 |