Modular Redux with TypeScript: Type-Safe Slices
Detail the creation of feature-based slices in Redux using TypeScript's type safety features, keeping code maintainable and scalable.
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface CounterState {
value: number;
}
const initialState: CounterState = { value: 0 };
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload;
},
},
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
This TypeScript code defines a 'counter' slice using Redux Toolkit's `createSlice` function. The state is type-safe with an interface, `CounterState`, and has an initial state. It includes three reducers: increment, decrement, and incrementByAmount, which are type-safe with the use of `PayloadAction`.
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
This code sets up a Redux store with the Redux Toolkit's `configureStore` function. It imports the `counterReducer` from the previously defined counter slice and includes it in the store. It also exports the `AppDispatch` and `RootState` types for use throughout the application.
// HTML structure
<div id="app">
<button id="increment">Increment</button>
<button id="decrement">Decrement</button>
<button id="incrementByAmount">Increment by 10</button>
<div id="value">0</div>
</div>
This HTML code defines a simple structure with three buttons for triggering different actions (increment, decrement, increment by a specific amount) and a `div` element to display the counter value.
/* CSS styles */
#app {
text-align: center;
margin-top: 50px;
}
button {
margin: 5px;
}
#value {
font-size: 2em;
margin-top: 20px;
}
This CSS code provides basic styling for the application, centering the content, styling the buttons, and increasing the font size of the counter display.
import { store } from './store';
import { increment, decrement, incrementByAmount } from './counterSlice';
document.getElementById('increment').addEventListener('click', () => {
store.dispatch(increment());
});
document.getElementById('decrement').addEventListener('click', () => {
store.dispatch(decrement());
});
document.getElementById('incrementByAmount').addEventListener('click', () => {
store.dispatch(incrementByAmount(10));
});
store.subscribe(() => {
document.getElementById('value').innerText = store.getState().counter.value.toString();
});
This JavaScript code sets up event listeners on the buttons and dispatches the appropriate actions. It subscribes to store updates and updates the counter display with the new state.