조금 복잡한 로직을 해볼거라고 함 Action에 payload 전달하기 여러 개의 state 속성 전달하기 Action에 payload 를 통해 값을 전달하면 더 다양하고 복잡한 로직을 처리할 수 있게 된다. Input을 통해 사용자로부터 값을 입력 받아 action를 처리해 줄 수도 있다. Store에서 여러 개의 데이터를 object 형태로 다룰 수 있다. 여러 개의 state의 속성을 다룰 때는 주의할 점이 있다. 항상 Reducer은 state를 덮어쓴다는 점이다. 만약 어떤 속성을 값을 입력하게 되지않으면, 그 값을 reducer는 undefined 처리하게 된다.
71강 실습 끝난거에서 시작함.
import { useSelector , useDispatch } from 'react-redux' ;
import classes from './Counter.module.css' ;
const Counter = () => {
const toggleCounterHandler = () => {};
const counter = useSelector (( state ) => state . counter );
const dispatch = useDispatch ();
const incrementHandler = () => {
dispatch ({ type : "increment" });
}
const decrementHandler = () => {
dispatch ({ type : "decrement" });
}
return (
< main className = { classes . counter } >
< h1 > Redux Counter </ h1 >
< div className = { classes . value } > { counter } </ div >
< button onClick = { toggleCounterHandler } > 토글 카운터 </ button >
< button onClick = { incrementHandler } > 증감 카운터 </ button >
< button onClick = { decrementHandler } > 감소 카운터 </ button >
</ main >
);
};
export default Counter ;
✅dispatch를 할 때 증가할 만큼의 숫자를 같이 담아서 그 숫자를 추가해주는 로직을 해볼거라고함.
mount 그걸 주고,
action.amount로 받아오기만 하면 되는거임.
리덕스의 리듀서는 state 값을 바꿀 때마다 새로운 state를 덮어쓰기 때문에 .. 실습 꼭 하기 안 덮어쓰게 하려면 …을 써야한다 (? 맞나?) …state 이렇게 써주면 바뀐 state는 바뀐 state로 적용하고 안 바뀐 state는 안 바뀐 state로 그냥 간다.
✅ 내 코드 적용이 안됐었다..그래서 3번쨰 if문이 죽어있었던거임.
import { createStore } from 'redux'
const counterReducer = ( state = { counter : 0 }, action ) => {
if ( action . type === 'increment' ){
return {
counter : state . counter + 1
}
}
if ( action . type === 'decrement' ){
return {
counter : state . counter - 1
}
}
return state ;
if ( action . type === 'increase' ){
return {
counter : state . counter + action . amount
}
}
return state ;
}
const store = createStore ( counterReducer );
export default store ;
그러면 counter가 10씩 잘 증가함.
✅이 숫자가 보여지는지 show and hide flag를 만들기
state에서 추가할 예정
if 문 toggle 추가
import { createStore } from 'redux'
const counterReducer = ( state = { counter : 0 , showCounter : true }, action ) => {
if ( action . type === 'increment' ){
return {
counter : state . counter + 1
}
}
if ( action . type === 'decrement' ){
return {
counter : state . counter - 1
}
}
if ( action . type === 'increase' ){
return {
counter : state . counter + action . amount
}
}
if ( action . type === 'toggle' ){
return {
showCounter : ! state . showCounter ,
}
}
return state ;
}
const store = createStore ( counterReducer );
export default store ;
toggleCounter
import { useSelector , useDispatch } from 'react-redux' ;
import classes from './Counter.module.css' ;
const Counter = () => {
const toggleCounterHandler = () => {
dispatch ({ type : "toggle" })
};
const counter = useSelector (( state ) => state . counter );
const dispatch = useDispatch ();
const incrementHandler = () => {
dispatch ({ type : "increment" });
}
const decrementHandler = () => {
dispatch ({ type : "decrement" });
}
const increase10Handler = () => {
dispatch ({ type : "increase" , amount : 10 });
}
return (
< main className = { classes . counter } >
< h1 > Redux Counter </ h1 >
< div className = { classes . value } > { counter } </ div >
< button onClick = { toggleCounterHandler } > 토글 카운터 </ button >
< button onClick = { incrementHandler } > 증감 카운터 </ button >
< button onClick = { increase10Handler } > 숫자 10 증가 카운터 </ button >
< button onClick = { decrementHandler } > 감소 카운터 </ button >
</ main >
);
};
export default Counter ;
여기서 끝이 아니라...
✅ 이 로직을 컴포넌트에도 적용을 해줘야지 바뀌는 변화들을 볼 수 있다.
Counter.js에서 showCounter라는 속성을 받아와야하는데 useSelctor를 이용해서 counter를 받아왔던 것처럼 showCounter도 마찬가지로 useSelector에서도 state에서 state.showCounter를 받아오도록 하겠습니다.
✅showCounter가 true면 보여주고 true 아니면 안 보여주고 showCounter && 이런 식으로 표현하면 됨
import { useSelector , useDispatch } from 'react-redux' ;
import classes from './Counter.module.css' ;
const Counter = () => {
const toggleCounterHandler = () => {
dispatch ({ type : "toggle" })
};
const counter = useSelector (( state ) => state . counter );
const showCounter = useSelector (( state ) => state . showCounter );
const dispatch = useDispatch ();
const incrementHandler = () => {
dispatch ({ type : "increment" });
}
const decrementHandler = () => {
dispatch ({ type : "decrement" });
}
const increase10Handler = () => {
dispatch ({ type : "increase" , amount : 10 });
}
return (
< main className = { classes . counter } >
< h1 > Redux Counter </ h1 >
{ showCounter && < div className = { classes . value } > { counter } </ div > }
< button onClick = { toggleCounterHandler } > 토글 카운터 </ button >
< button onClick = { incrementHandler } > 증감 카운터 </ button >
< button onClick = { increase10Handler } > 숫자 10 증가 카운터 </ button >
< button onClick = { decrementHandler } > 감소 카운터 </ button >
</ main >
);
};
export default Counter ;
✅자바스크립트의 논리연산자 &&
JavaScript의 논리 연산자인 "AND" (&&)를 사용하여 조건을 간결하게 표현한 부분입니다. JavaScript에서 && 연산자는 두 개의 피연산자가 모두 true일 때만 true를 반환하고, 그렇지 않으면 첫 번째 false 값을 반환합니다. 따라서 {showCounter && <div className={classes.value}>{counter}</div>}에서는 showCounter가 true일 때만 <div className={classes.value}>{counter}</div> 부분이 평가되어 나타납니다. 만약 showCounter가 false이면, false로 평가되고 두 번째 피연산자인 <div> 부분은 무시됩니다. 이런 방식으로 코드를 작성하면 showCounter의 값에 따라 특정 부분을 간결하게 표현할 수 있습니다. 이는 조건부 렌더링을 위한 일반적인 JavaScript의 표현 방식 중 하나입니다.
✅ 토글카운터를 누르면 숫자가 사라짐.
✅ 어떤 속성을 바꿔줄때 다른 속성을 챙기지 않으면 그 안챙겨준 값들은 없는 값들로 된다.
지금 counterReducer에는 2개의 속성이 있음. {counter: 0, showCounter:true} if(action.type === 'toggle'){ return { showCounter: !state.showCounter, } } 여기에는 toggle이라는 타입에 액션을 했을 때 리턴으로 showCounter를 보여주고 있는데 이 말은 counter라는 속성이 없어진거임. redux는 리듀서로 state바꿀때마다 새로운 state 덮어써서 counter는 undefined가 됨 그래서 안보이는거임.
before
import { createStore } from 'redux'
const counterReducer = ( state = { counter : 0 , showCounter : true }, action ) => {
if ( action . type === 'increment' ){
return {
counter : state . counter + 1
}
}
if ( action . type === 'decrement' ){
return {
counter : state . counter - 1
}
}
if ( action . type === 'increase' ){
return {
counter : state . counter + action . amount
}
}
if ( action . type === 'toggle' ){
return {
showCounter : ! state . showCounter ,
}
}
return state ;
}
const store = createStore ( counterReducer );
export default store ;
✅그래서 카운터 1씩 다 올리고 토글 카운터 하고 나서 다시 펼쳐도 카운터 그대로 있다.
✅다른 if문들도 다른 state 다 챙겨야하는데, 다른 데서는 느낌표 없어야함.
import { createStore } from 'redux'
const counterReducer = ( state = { counter : 0 , showCounter : true }, action ) => {
if ( action . type === 'increment' ){
return {
counter : state . counter + 1 ,
showCounter : state . showCounter ,
}
}
if ( action . type === 'decrement' ){
return {
counter : state . counter - 1 ,
showCounter : state . showCounter ,
}
}
if ( action . type === 'increase' ){
return {
counter : state . counter + action . amount ,
showCounter : state . showCounter , /*이 위의 애들도 다 해줘야함*/
}
}
if ( action . type === 'toggle' ){
return {
counter : state . counter ,
showCounter : ! state . showCounter ,
}
}
return state ;
}
const store = createStore ( counterReducer );
export default store ;
✅ 그냥...state하면 된다.
그리고 또다른 방법은 속성이 2개밖에 없을 때는 일일이 추가해주는게 어렵지않아요. state의 모든 값이 바뀔 수 있겠지만 어떤 값은 안 바뀌고 어떤 값은 바뀌고 그럴 수 있는데 ...를 이용해서 바뀌는 값만 바꿔주게 한다. 안 바뀐 값은 그대로 기존 값 유지
import { createStore } from 'redux'
const counterReducer = ( state = { counter : 0 , showCounter : true }, action ) => {
if ( action . type === 'increment' ){
return {
... state ,
counter : state . counter + 1 ,
}
}
if ( action . type === 'decrement' ){
return {
... state ,
counter : state . counter - 1 ,
}
}
if ( action . type === 'increase' ){
return {
... state ,
counter : state . counter + action . amount ,
}
}
if ( action . type === 'toggle' ){
return {
... state ,
showCounter : ! state . showCounter ,
}
}
return state ;
}
const store = createStore ( counterReducer );
export default store ;