Palette
    Preparing search index...

    State management can go from trivial to complex quickly as your code develops.

    The State class offered by Palette is powerful, flexible, and offers advanced deep reactivity observation.

    The Component class deeply integrates with the State system, re-rendering whenever a new state is computed. You can use the built-in state in components, or create standalone State instances for shared state or stores.

    The State class is generic, taking a type parameter representing the shape of the stateful data. State must be an object.

    interface AppStateShape {
    view: "home" | "profile";
    username: string;
    lastInteraction: Date;
    settings: {
    invisible: boolean;
    tags: string[];
    }
    }

    const appState = new State<AppStateShape>({
    view: "home",
    username: "jason-bourne",
    lastInteraction: new Date(),
    settings: {
    invisible: true,
    tags: ["not-tom-cruise"],
    }
    });

    You can add listeners to state instances which will run whenever state changes:

    appState.addListener((data) => {
    console.log(`Jesus Christ, that's ${data.username}`);
    })

    Or you can fetch data manually:

    appState.get("view") // => "home"
    appState.current.username // => "jason-bourne"

    But what good is state if we can't change it up?

    There's a bunch of ways to change state depending on what you need. Pick yer poison.

    // A simple set of a top level property
    appState.set("view", "profile");

    // Update multiple things at once
    appState.patch({
    view: "home",
    lastInteraction: new Date(),
    });

    // Functional mutation
    appState.mutate((state) => {
    // You can safely modify `state` here, it's a deep clone
    state.view = "home";
    return state;
    });

    // Transaction-style mutation
    appState.transaction((state) => {
    // `state` is a cloned, full State instance
    state.set("view", "home");
    state.set("lastInteraction", new Date());
    });

    // Live accessor with deep reactivity
    state.live.view = "profile";

    // Nested updates supported
    state.live.settings.invisible = false;

    // Array mutators are also supported
    state.live.settings.tags.push("another-one");

    At any time, you can wipe away the whole state and replace it, forcing all listeners to receive the new state data.

    appState.replace({
    view: "home",
    username: "tom-cruise",
    lastInteraction: new Date(),
    settings: {
    invisible: false,
    tags: ["is-tom-cruise"],
    },
    })