Advanced

React Context

Share state between components without prop drilling

  • context
  • local state

Key concepts

count is a server prop, assigned on the LiveView exactly like the Counter example. React's own createContext/useContext then shares that value with a nested component with no prop passed between them — the two mechanisms compose, they don't conflict.

Context.tsx
import React, { createContext, useContext } from "react";
import { useLiveReact } from "live_react";

// `count` comes from the server, but only the provider at the top needs to
// know that — everything below reads it from context, with no prop drilling.
const CountContext = createContext<number>(0);

function CountDisplay() {
  const count = useContext(CountContext);
  return <span className="text-xl">{count}</span>;
}

export function Context({ count }: { count: number }) {
  const { pushEvent } = useLiveReact();

  return (
    <CountContext.Provider value={count}>
      <div className="flex items-center gap-6">
        <button
          className="rounded-md border px-3 py-1"
          onClick={() => pushEvent("set_count", { value: count - 1 })}
        >
          −1
        </button>
        <CountDisplay />
        <button
          className="rounded-md border px-3 py-1"
          onClick={() => pushEvent("set_count", { value: count + 1 })}
        >
          +1
        </button>
      </div>
    </CountContext.Provider>
  );
}

How it works

Context wraps its children in a CountContext.Provider whose value is the server-owned count prop. Any component inside that tree — however deeply nested — can call useContext(CountContext) to read it, without every component in between having to accept and forward a count prop it doesn't otherwise need.

Clicking a button still calls pushEvent("set_count", …), which reaches handle_event/3 and reassigns count on the server, same as Counter — context describes how a value moves around inside React, not where it comes from.