DEV Community

Cover image for Types of state management
Wafa Bergaoui
Wafa Bergaoui

Posted on

Types of state management

Introduction

State management is a critical aspect of software development, enabling applications to handle data consistently and efficiently. This guide explores various state management approaches, types, and best practices across different frameworks and libraries, providing a holistic understanding of the topic.

Types of State Management

1. Centralized State Management
Centralized state management involves storing the entire application's state in a single, centralized store. This approach ensures a single source of truth, making it easier to manage and debug the state.

Example: Redux (React)
Redux is a popular centralized state management library for React applications. It uses a single store to manage the entire state and follows a strict unidirectional data flow.

import { createStore } from 'redux';

// Reducer function
function counterReducer(state = { count: 0 }, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    default:
      return state;
  }
}

// Create store
const store = createStore(counterReducer);

// Dispatch actions
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // { count: 1 }

Enter fullscreen mode Exit fullscreen mode

2. Reactive State Management

Reactive state management allows state to be updated automatically in response to changes, typically using observables or reactive programming principles. This approach is particularly useful for real-time applications.

Example: MobX (React)
MobX is a library that enables reactive state management using observable state and reactions.

import { observable, action } from 'mobx';

class Store {
  @observable count = 0;

  @action increment() {
    this.count++;
  }
}

const store = new Store();
store.increment();
console.log(store.count); // 1

Enter fullscreen mode Exit fullscreen mode

3. Atomic State Management
Atomic state management breaks the state into small, independent units (atoms) that can be managed and updated individually. This approach allows for fine-grained control over the state.

Example: Recoil (React)
Recoil is a state management library for React that uses atoms to represent state pieces.

import { atom, useRecoilState } from 'recoil';

// Atom
const countState = atom({
  key: 'countState',
  default: 0,
});

function Counter() {
  const [count, setCount] = useRecoilState(countState);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Categories of State

1. Local State
Local state is confined to a single component and managed internally using hooks like useState in React or state variables in other frameworks.

Example: React useState

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

2. Global State
Global state is shared across multiple components and managed using context or global stores.

Example: React Context API

import React, { createContext, useContext, useState } from 'react';

const CountContext = createContext();

function CountProvider({ children }) {
  const [count, setCount] = useState(0);

  return (
    <CountContext.Provider value={{ count, setCount }}>
      {children}
    </CountContext.Provider>
  );
}

function Counter() {
  const { count, setCount } = useContext(CountContext);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

function App() {
  return (
    <CountProvider>
      <Counter />
    </CountProvider>
  );
}

Enter fullscreen mode Exit fullscreen mode

3. Server State
Server state refers to data fetched from a server that needs to be synchronized with the client state. Tools like React Query and SWR are used to manage server state effectively.

Example: React Query

import { useQuery } from 'react-query';

function fetchCount() {
  return fetch('/api/count').then((res) => res.json());
}

function Counter() {
  const { data, error, isLoading } = useQuery('count', fetchCount);

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error loading count</div>;

  return <div>Count: {data.count}</div>;
}

Enter fullscreen mode Exit fullscreen mode

4. Form State
Form state manages data within form components, including user input and validation states.

Example: Formik (React)

import { useFormik } from 'formik';

function MyForm() {
  const formik = useFormik({
    initialValues: { email: '' },
    onSubmit: values => {
      console.log(values);
    },
  });

  return (
    <form onSubmit={formik.handleSubmit}>
      <input
        name="email"
        type="email"
        onChange={formik.handleChange}
        value={formik.values.email}
      />
      <button type="submit">Submit</button>
    </form>
  );
}

Enter fullscreen mode Exit fullscreen mode

Best Practices for State Management

- Keep State Minimal: Only store the necessary state to avoid complexity.

- Use Derived State: Compute derived state from existing state instead of storing redundant data.

- Encapsulate State: Encapsulate state management logic to keep components clean and focused on UI rendering.

- Choose the Right Tool: Use appropriate state management tools based on the complexity and requirements of your application.

Conclusion

Effective state management is key to building robust and maintainable applications. By understanding and applying different state management approaches and types, you can ensure your applications are responsive, efficient, and scalable.

Top comments (0)