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.