Skip to content

Working with state

When building interactive UIs, managing state is crucial. GamefaceUI components use SolidJS reactivity. This page shows how to get component state and react to it without surprises.

For the following examples, we will use the ToggleButton component, but the same principles apply to other components as well.

Most components expose their current state through a ref prop. This ref is an object that contains methods and properties to interact with the component programmatically.

To get the current state of a component using its ref:

  1. Declare a variable with the appropriate type for the component’s ref (e.g., ToggleButtonRef for the ToggleButton component).
  2. Pass this variable to the component’s ref prop.
  3. Call the ref’s methods (e.g., toggleRef.checked()) to get the current state.
import ToggleButton, { ToggleButtonRef } from '@components/Basic/ToggleButton/ToggleButton';
const App = () => {
let toggleRef!: ToggleButtonRef;
const handleKeyPress = (e: KeyboardEvent) => {
if (e.keyCode !== 13) return // enter key
console.log(toggleRef.checked());
}
return (
<>
<ToggleButton ref={toggleRef!} keypress={handleKeyPress} />
</>
);
};

Many components provide an onChange prop that allows you to get the up-to-date state of a component whenever it changes.

To get the current state of a component using the onChange prop:

  1. Define a state variable (e.g., using createSignal) to store the component’s state.
  2. Pass a callback to the onChange prop that updates this state variable.
  3. Use the state variable wherever you need the component’s state.
import { createSignal } from 'solid-js';
import ToggleButton from '@components/Basic/ToggleButton/ToggleButton';
const App = () => {
const [isChecked, setIsChecked] = createSignal(false);
return (
<>
<ToggleButton onChange={setIsChecked} />
<div>The toggle is {isChecked() ? 'ON' : 'OFF'}</div>
</>
);
};

Let’s say you want to display some content after a user toggles a switch. To achieve this you will need to “react” to the component’s state changes. To do this, you need to:

  1. Retrieve the state of the component.
  2. Use this state to conditionally render or update other parts of your UI.

At first glance, directly using the component’s ref seems like the simplest way to do this. However, reading a ref inside a reactive condition is brittle: on the first render the ref variable is still undefined, and plain variables aren’t reactive, so the condition won’t re-evaluate when the ref gets assigned. In other words, code like this won’t work:

import ToggleButton, { ToggleButtonRef } from '@components/Basic/ToggleButton/ToggleButton';
import { Show } from 'solid-js';
const App = () => {
let toggleRef!: ToggleButtonRef;
return (
<>
<ToggleButton ref={toggleRef!} />
<Show when={toggleRef!.checked()}>
<div>The toggle is ON</div>
</Show>
</>
);
};

Here is a working example using the onChange prop:

import ToggleButton, { ToggleButtonRef } from '@components/Basic/ToggleButton/ToggleButton';
import { Show } from 'solid-js';
const App = () => {
const [isChecked, setIsChecked] = createSignal(false);
return (
<>
<ToggleButton onChange={setIsChecked} />
<Show when={isChecked()}>
<div>The toggle is ON</div>
</Show>
</>
);
};

This approach leverages SolidJS’s reactivity to bind the state to a signal and update the UI whenever the toggle state changes.