React Example

State Management

Learn how to manage state effectively in React applications

Local State

Component-level state management

useState Hook

import { useState } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);
  const [error, setError] = useState(null);

  const increment = () => {
    try {
      setCount(prev => prev + 1);
    } catch (err) {
      setError('Failed to increment');
    }
  };

  if (error) return 
Error: {error}
; return (

Count: {count}

); };

Key Points

  • Initialize state with useState
  • Use functional updates for derived state
  • Handle errors gracefully
  • Keep state minimal and focused

Context API

Sharing state across components

Theme Context Example

// ThemeContext.js
import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext();

export const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };

  return (
    
      {children}
    
  );
};

// Using the context
const ThemedButton = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    
  );
};

Key Points

  • Create context with createContext
  • Provide context with Provider component
  • Consume context with useContext
  • Avoid prop drilling

Reducers

Managing complex state logic

Todo Reducer

import { useReducer } from 'react';

const initialState = {
  todos: [],
  loading: false,
  error: null
};

function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        ...state,
        todos: [...state.todos, action.payload]
      };
    case 'REMOVE_TODO':
      return {
        ...state,
        todos: state.todos.filter(todo => todo.id !== action.payload)
      };
    case 'SET_LOADING':
      return {
        ...state,
        loading: action.payload
      };
    default:
      return state;
  }
}

const TodoList = () => {
  const [state, dispatch] = useReducer(todoReducer, initialState);

  const addTodo = (text) => {
    dispatch({
      type: 'ADD_TODO',
      payload: { id: Date.now(), text }
    });
  };

  return (
    
{state.loading ? (
Loading...
) : (
    {state.todos.map(todo => (
  • {todo.text}
  • ))}
)}
); };

Key Points

  • Use reducers for complex state
  • Define clear action types
  • Keep reducers pure
  • Handle all action cases

Global State

Application-wide state management

Redux Store Example

// store/index.js
import { configureStore } from '@reduxjs/toolkit';
import authReducer from './authSlice';
import todoReducer from './todoSlice';

export const store = configureStore({
  reducer: {
    auth: authReducer,
    todos: todoReducer
  }
});

// Component usage
import { useSelector, useDispatch } from 'react-redux';
import { login } from './authSlice';

const LoginForm = () => {
  const dispatch = useDispatch();
  const { isAuthenticated } = useSelector(
    state => state.auth
  );

  const handleLogin = (credentials) => {
    dispatch(login(credentials));
  };

  return (
    
{/* Form fields */}
); };

Key Points

  • Use Redux for large applications
  • Organize state by feature
  • Use Redux Toolkit for best practices
  • Implement proper selectors