Redux 활용하기
Counter에 기능 추가하기
이번 장에서는 앞서 살펴 본 Counter 예제에 기능들을 추가하면서 Redux를 활용하는 방법에 대해 좀 더 자세히 살펴보도록 하겠습니다.
증감하는 수량 설정하기
앞선 Counter 예제에서는 증가와 감소 버튼을 누를 때마다 Count 값이 1씩 증가하거나 감소하였습니다. 이번에는 Redux를 활용하여 사용자가 증감하는 수량을 직접 설정할 수 있도록 구현해 봅시다.
우선 counterSlice 컴포넌트에 증감하는 수량을 설정하기 위한 Reducer 함수인 incrementByQuantity()를 정의합니다. 이때 사용되는 Action 객체의 payload 필드에는 Action의 타입에 따라 실행에 필요한 추가적인 state값을 저장할 수 있습니다.
counterSlice.js
export const counterSlice = createSlice({
// ...
reducers: {
// ...
incrementByQuantity: (state, action) => {
state.value += action.payload;
}
}
});
export const {
increment,
decrement,
incrementByQuantity
} = counterSlice.actions;
export const selectCount = (state) => state.counter.value;
export default counterSlice.reducer;
예제(App.js)
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import {
decrement,
increment,
incrementByQuantity,
selectCount
} from "./counterSlice";
const App = () => {
const count = useSelector(selectCount);
const dispatch = useDispatch();
const [incrementQuantity, setIncrementQuantity] = useState("2");
return (
<div>
<div>
// ...
</div>
<div>
<input
value={incrementQuantity}
onChange={(e) => setIncrementQuantity(e.target.value)}
/>
<button
onClick={() =>
dispatch(incrementByQuantity(Number(incrementQuantity)))
}
>
씩 증가
</button>
</div>
</div>
);
};
export default App;
비동기적으로 증감시키기
이번에는 Count 값을 증가시키는 버튼을 눌렀을 때 1초 간의 딜레이 후 동작하도록 기능을 추가해 보도록 하겠습니다.
우선 counterSlice 컴포넌트에 아래 코드를 추가합니다. 아래 함수는 보통 thunk라고 불리며, 비동기 로직을 수행할 수 있도록 해 주는 코드입니다. 이 함수는 일반 Action처럼 Dispatch 될 수 있습니다. 이제 Dispatch 함수의 첫 번째 인수로 thunk가 호출되며, 이후 비동기 코드가 실행되고 다른 Action들이 Dispatch 될 것입니다.
counterSlice.js
// ...
export const incrementAsync = (quantity) => (dispatch) => {
setTimeout(() => {
dispatch(incrementByQuantity(quantity));
}, 1000);
};
// ...
예제(App.js)
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import {
decrement,
increment,
incrementByQuantity,
incrementAsync,
selectCount
} from "./counterSlice";
const App = () => {
// ...
return (
<div>
<div>
// ...
</div>
<div>
// ...
<button
onClick={() =>
dispatch(incrementAsync(Number(incrementQuantity) || 0))
}
>
씩 증가(비동기)
</button>
</div>
</div>
);
};
export default App;