Redux State Management Examples and React Hooks Performance
Redux Task Store Implementation
1. Setup and Initial State
Import createStore from Redux. Note: In modern Redux Toolkit, this function is deprecated in favor of configureStore.
const { createStore } = require('redux'); // Or 'import { createStore } from 'redux';'
const initialState = { tasks: [] };
2. Action Types & Creators
Define actions for adding and removing tasks.
const ADD_TASK = 'ADD_TASK';
const REMOVE_TASK = 'REMOVE_TASK';
function addTask(task) { // task: { id, description }
return { type: ADD_TASK, payload: task };
}
function removeTask(taskId) { // taskId: number
return { type: REMOVE_TASK, payload: taskId };
}
3. Task Reducer Logic
The reducer handles state transitions immutably.
function taskReducer(state = initialState, action) {
switch (action.type) {
case ADD_TASK:
return { ...state, tasks: [...state.tasks, action.payload] }; // Add new task to a new array
case REMOVE_TASK:
return { ...state, tasks: state.tasks.filter(task => task.id !== action.payload) }; // Filter out task by id
default:
return state; // Return current state if action is unknown
}
}
4. Store Creation and Dispatching
Create the store and subscribe to changes.
const store = createStore(taskReducer);
// Listener for state changes
const unsubscribe = store.subscribe(() => {
console.log('--- Store Updated ---');
console.log('New State:', JSON.stringify(store.getState(), null, 2));
console.log('---------------------');
});
console.log('Initial State:', JSON.stringify(store.getState(), null, 2));
console.log('\nDispatching: addTask({ id: 1, description: "Write report" })');
store.dispatch(addTask({ id: 1, description: 'Write report' }));
console.log('\nDispatching: addTask({ id: 2, description: "Attend meeting" })');
store.dispatch(addTask({ id: 2, description: 'Attend meeting' }));
console.log('\nDispatching: removeTask(1)');
store.dispatch(removeTask(1)); // Removes task with id 1
unsubscribe(); // Stop listening to store updates
Simple Redux Bank Account Example
A second example demonstrating a simple withdrawal mechanism.
const redux = require('redux');
const createStore = redux.createStore;
function withdraw(){
return{
type: "Withdraw_Money",
payload: 50
}
}
const initialState = {
amount: 1000
}
const reducer = (prevState=initialState, action) => {
switch(action.type){
case "Withdraw_Money":
return {
...prevState,
amount: prevState.amount - action.payload
}
default:
return prevState
}
}
const store = createStore(reducer);
console.log("Initial state: ", store.getState());
const unsubscribe = store.subscribe(()=>{
console.log("Updated store: ", store.getState())
})
store.dispatch(withdraw())
store.dispatch(withdraw())
store.dispatch(withdraw())
unsubscribe();
store.dispatch(withdraw());
React Component: Product Dashboard with Performance Hooks
This React component fetches products, handles search filtering, and utilizes useMemo and useCallback for optimization.
import React, { useState, useEffect, useMemo, useRef, useCallback } from 'react';
import axios from 'axios'; // Correct: import axios directly
function ProductDashboard() {
// State for all products fetched from API
const [allProducts, setAllProducts] = useState([]);
// State for the current search term entered by the user
const [searchTerm, setSearchTerm] = useState('');
// State for loading status
const [loading, setLoading] = useState(false);
// State for error messages
const [error, setError] = useState(null);
// 1. Fetch product data from a remote API
useEffect(() => {
const fetchData = async () => {
setLoading(true);
setError(null);
try {
// Use the public API: https://fakestoreapi.com/products
const response = await axios.get('https://fakestoreapi.com/products');
setAllProducts(response.data || []); // Ensure it's an array
} catch (err) {
setError(err.message || 'Failed to fetch products. Please try again.');
console.error("Failed to fetch products:", err);
} finally {
setLoading(false);
}
};
fetchData();
}, []); // Empty dependency array to run once on mount
// 3. Enhance UX using useRef: Autofocus search input
const searchInputRef = useRef(null);
useEffect(() => {
if (searchInputRef.current) {
searchInputRef.current.focus();
}
}, []); // Focus on mount
// Handler for search input changes (updates searchTerm state)
const handleSearchInputChange = useCallback((event) => {
setSearchTerm(event.target.value);
}, []); // setSearchTerm is stable, so [] is fine.
// 5. Optimize filtering logic using useCallback:
// Memoize the actual filtering function used inside useMemo for filteredProducts
const filterLogic = useCallback(
(product) => {
// Ensure product.title exists and is a string before calling toLowerCase
if (typeof product.title !== 'string') {
return false;
}
return product.title.toLowerCase().includes(searchTerm.toLowerCase());
},
[searchTerm] // This callback depends only on searchTerm
);
// 4. Use useMemo for performance: Create a memoized filteredProducts array
const filteredProducts = useMemo(() => {
if (!searchTerm.trim()) {
// If search term is empty or only whitespace, show all products
return allProducts;
}
return allProducts.filter(filterLogic);
}, [allProducts, searchTerm, filterLogic]); // Recalculate if these change
// 4. Use useMemo for performance: Create a memoized variable totalProducts to count the number of products
const totalProductsCount = useMemo(() => allProducts.length, [allProducts]);
// 6. Render Output
return (
Product Dashboard
{/* Search input box with autofocus */}
{/* Handle loading state */} {loading &&
Loading products…
}
{/* Handle error state */} {error &&
Error: {error}
}
{/* Display content only if not loading and no error */} {!loading && !error && ( <> {/* Text showing: Total Products: X | Filtered Products: Y */}
Total Products: {totalProductsCount} | Filtered Products: {filteredProducts.length}
{/* A list of product titles that match the search filter */} {allProducts.length > 0 ? ( filteredProducts.length > 0 ? (
- {filteredProducts.map(product => (
- {product.title} ))}
{searchTerm ? ‘No products match your search.’ : ‘No products found.’}
) ) : (No products available to display.
)} > )}); }
export default ProductDashboard;
