1) 숫자 증감
const Counter = () => {
const { counter } = useSelector(state => state.counterR)
const dispatch = useDispatch()
return (
<div>
<h2>카운트 : {counter}</h2>
<p>
<button onClick={()=>dispatch(minus(10))}>-10</button>
<button onClick={()=>dispatch(minus())}>-1</button>
<button onClick={()=>dispatch(plus())}>+1</button>
<button onClick={()=>dispatch(plus(10))}>+10</button>
</p>
</div>
);
};
화면에 출력될 Counter 컴포넌트이다.
버튼이 총 4개 있는데 두 버튼은 전달해 주는 매개변수가 있고 나머지 두 버튼은 없다.
import { createSlice } from '@reduxjs/toolkit'
const initialState = { counter: 0 }
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
plus: (state, action) => {
action.payload ??= 1;
state.counter += action.payload
},
minus: (state, action) => {
action.payload ??= 1;
state.counter -= action.payload
},
}
})
export const { plus, minus } = counterSlice.actions
export default counterSlice.reducer
이 경우에 전달받은 매개변수 값이 없으면 action.payload가 undefinded를 출력하게 되는데 이를 인식해 1을 증감시켜주도록 했다.
??= 연산자의 경위 좌변이 null / undefinded일때 우변의 값을 갖는다.
따라서 매개변수가 없는 minus() / plus()의 경우 action.payload = 1이 된다.
2) 목록 관리
const TodosList = () => {
const { data } = useSelector(state => state.todosR)
return (
<div>
{
data.map(item => <TodosItem key={item.id} item={item}/>)
}
</div>
);
};
const TodosItem = ({ item }) => {
const { id, text, isChk } = item
const dispatch = useDispatch()
return (
<li style={{ color: isChk ? 'lightgray' : 'black' }}>
<input type='checkbox' checked={isChk} onChange={() => dispatch(toggleTodo(id))} />
{text}
<button onClick={() => dispatch(delTodo(id))}>삭제</button>
</li>
);
};
목록을 관리하는 Todo 예제를 구현했다.
data는 Slice 파일에 저장되고 관리되기 때문에 useSelector를 이용해 불러온다.
item 컴포넌트에선 dispatch를 이용해 두 함수를 가져왔다.
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
subject: "과목",
// data: [
// { id: 1, text: '인공지능', isChk: false },
// { id: 2, text: '객체지향프로그래밍', isChk: true },
// { id: 3, text: 'C프로그래밍', isChk: false },
// { id: 4, text: '정보보호', isChk: true },
// { id: 5, text: '웹프로그래밍', isChk: true },
// ]
data: localStorage.getItem('data') ? JSON.parse(localStorage.getItem('data')) : [
{ id: 1, text: '인공지능', isChk: false },
{ id: 2, text: '객체지향프로그래밍', isChk: true },
{ id: 3, text: 'C프로그래밍', isChk: false },
{ id: 4, text: '정보보호', isChk: true },
{ id: 5, text: '웹프로그래밍', isChk: true },
]
}
let no = 6
export const todosSlide = createSlice({
name: "todo",
initialState,
reducers: {
addTodo: (state, action) => {
// state.data = [
// ...state.data,
// {
// id: no++,
// subject: action.payload,
// isChk: false
// }
// ]
state.data.push({id:no++, text : action.payload, isChk : false})
localStorage.setItem('data',JSON.stringify(state.data))
},
delTodo: (state, action) => {
state.data = state.data.filter(item => item.id !== action.payload)
localStorage.setItem('data',JSON.stringify(state.data))
},
toggleTodo: (state, action) => {
state.data = state.data.map(item => item.id === action.payload ? { ...item, isChk: !item.isChk } : item)
localStorage.setItem('data',JSON.stringify(state.data))
},
changeInput: (state, action) => {
state.text = action.payload
},
},
}
)
export const { delTodo, toggleTodo, changeInput, addTodo } = todosSlide.actions;
export default todosSlide.reducer;
localstorage 방식으로 데이터를 저장하기 위해 기존 코드를 주석처리 하였다.
Slice에선 함수를 선언하고 관리하며 data도 관리한다.
javascript 문법을 사용할 수 있기 때문에 push로 새로운 요소를 추가할 때 data에 저장되도록 했다.
const TodosInput = () => {
const { text } = useSelector(state => state.todosR)
const dispatch = useDispatch()
const onSubmit = e => {
e.preventDefault()
dispatch(addTodo(text))
dispatch(changeInput(''))
}
return (
<form onSubmit={onSubmit}>
<input type="text" onChange={(e) => dispatch(changeInput(e.target.value))} value={text} placeholder='과목'/>
</form>
);
};
input에선 마찬가지로 useDispatch를이용해 addTodo함수와 changeInput 함수를 호출해 사용했다.
마지막으로 어제 색상 변경 예제를 활용하여 해당 컴포넌트로 color가 변경되었을 때 과목관리의 style : color가 변경되도록 했다.
const { color } = useSelector(state => state.color)
return (
<div>
<h1 style={{ color: color }}>과목관리</h1>