Types of state management
Tags: frontend, react, development, javascript
Published: 2024-06-28 11:31:23

## **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.

```javascript
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 }

```

## **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.

```javascript
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

```

**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.

```javascript
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>
  );
}

```

## **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

```javascript
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>
  );
}

```

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

**Example:** React Context API

```javascript
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>
  );
}

```
**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

```javascript
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>;
}

```

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

**Example:** Formik (React)

```javascript
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>
  );
}

```
**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.