Skip to content

RESOURCES / BLOG

What is State in JavaScript?

Every interactive app keeps track of things that can change over time: user input, network responses, UI toggles, media loading progress, and more. In community threads, you often see devs wrestle with questions like where to store data, how to update it predictably, and how to keep the UI in sync.

What is state in JavaScript? How is it different from props or plain variables, where should it live in a web app, and what are reliable patterns to update state without bugs? I use both vanilla JS and frameworks like React, so examples for both would help.

In JavaScript, state is the data that represents the current reality of your application at a given time. When state changes, your app behavior or UI should update to reflect it. State can be ephemeral in memory, persisted in storage, or fetched from servers.

  • Local state. Variables captured in a closure or inside a component to track UI specifics like a modal open flag.
  • Application state. Global data shared across screens, such as an authenticated user or cart items.
  • Server state. Data that comes from APIs and can become stale, requiring caching, revalidation, and error handling.
  • URL state. Information encoded in the URL query or hash that controls filters, pagination, or selected items.
  • Persisted state. Data saved to localStorage or IndexedDB that survives page reloads.
  • Single source of truth. Keep each piece of state in one place and derive the rest when possible.
  • Immutability on update. Avoid in-place mutation to make changes predictable and easier to debug.
  • Pure transitions. Prioritize using pure functions to transform the previous state into the next state based on an action.
  • Explicit side effects. Perform IO like fetches or storage writes around state transitions, not inside them.
// Minimal store pattern using a closure
function createStore(initialState) {
  let state = initialState;
  const subs = new Set();

  function getState() { return state; }
  function subscribe(fn) { subs.add(fn); return () => subs.delete(fn); }
  function setState(updater) {
    const next = typeof updater === 'function' ? updater(state) : updater;
    if (next !== state) {
      state = next;
      subs.forEach(fn => fn(state));
    }
  }

  return { getState, setState, subscribe };
}

// Counter example
const store = createStore({ count: 0 });

const $value = document.getElementById('value');
const $inc = document.getElementById('inc');
const $dec = document.getElementById('dec');

store.subscribe(s => { $value.textContent = s.count; });
$inc.addEventListener('click', () => store.setState(s => ({ ...s, count: s.count + 1 })));
$dec.addEventListener('click', () => store.setState(s => ({ ...s, count: s.count - 1 })));

// Initial render
$value.textContent = store.getState().count;Code language: JavaScript (javascript)
import { useState, useReducer } from 'react';

// Simple array updates
function Cart() {
  const [items, setItems] = useState([]);
  function addItem(item) {
    setItems(prev => [...prev, item]); // do not mutate prev directly
  }
  return <button onClick={() => addItem({ id: Date.now() })}>Add item</button>;
}

// Complex transitions with useReducer
function reducer(state, action) {
  switch (action.type) {
    case 'add': return { ...state, count: state.count + 1 };
    case 'sub': return { ...state, count: Math.max(0, state.count - 1) };
    default: return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });
  return (
    <div>
      <span>{state.count}</span>
      <button onClick={() => dispatch({ type: 'add' })}>+</button>
      <button onClick={() => dispatch({ type: 'sub' })}>-</button>
    </div>
  );
}Code language: JavaScript (javascript)

Server state can arrive out of order. Cancel in-flight requests when a new one starts to prevent stale updates.

let controller = new AbortController();

async function search(query) {
  controller.abort();              // cancel previous
  controller = new AbortController();
  const res = await fetch(`/api?q=${encodeURIComponent(query)}`, { signal: controller.signal });
  const data = await res.json();
  renderResults(data);
}Code language: JavaScript (javascript)
function save(key, value) {
  localStorage.setItem(key, JSON.stringify(value));
}
function load(key, fallback) {
  try { return JSON.parse(localStorage.getItem(key)) ?? fallback; }
  catch { return fallback; }
}Code language: JavaScript (javascript)

Suppose your app tracks user preference and network info in state, then builds the right transformation URL on the fly.

// Example: pick format and width from state to construct a Cloudinary URL
function buildImageUrl({ format, width, publicId }) {
  const base = 'https://res.cloudinary.com/demo/image/upload';
  const transform = `f_${format},q_auto,w_${width},c_fill`;
  return `${base}/${transform}/${publicId}.jpg`; // publicId can omit extension if configured
}

// State-driven rendering
const state = { prefersWebP: true, width: 800, publicId: 'sample' };
const format = state.prefersWebP ? 'webp' : 'jpg';
const url = buildImageUrl({ format, width: state.width, publicId: state.publicId });
// <img src={url} alt="Product" />Code language: JavaScript (javascript)

This ties your UI state directly to media delivery: toggling a quality slider, switching lightbox sizes, or adapting to slow networks can update transformation parameters and keep experiences snappy and consistent.

  • State is the data that drives behavior and UI at a point in time.
  • Keep a single source of truth, update immutably, and isolate side effects.
  • Use closures or small stores in vanilla JS, and hooks or reducers in React for predictable updates.
  • Handle async with cancellation to avoid stale data, and persist only what you must.
  • Let state drive media delivery decisions like format and size to improve performance and UX.

Ready to let your app state drive smarter media delivery and performance? Sign up for Cloudinary and start optimizing today.

Start Using Cloudinary

Sign up for our free plan and start creating stunning visual experiences in minutes.

Sign Up for Free