Skip to content

Instantly share code, notes, and snippets.

@noahlt
Created August 24, 2020 15:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noahlt/95bd3fb7d449d8819680a64cf1618225 to your computer and use it in GitHub Desktop.
Save noahlt/95bd3fb7d449d8819680a64cf1618225 to your computer and use it in GitHub Desktop.
Setter Component Hook

Playing with React over the weekend, I made a hook that’s like useState except instead of returning a setter function it returns a component you can render:

function usePercentageSlider(label, initialValue) {
  const [value, setValue] = useState(initialValue);
  return [
    value,
    <div>
      <div>
        {label} {value}:
      </div>
      <div>
        <input
          type="range"
          value={value}
          onChange={(e) => setValue(e.target.value)}
          min="0"
          max="1"
          step="0.01"
        />
      </div>
    </div>,
  ];
}

The idea is that the only way to set the value of foo is via the UI component fooSlider:

function App() {
  const [foo, fooSlider] = usePercentageSlider("foo slider", 0);
  return (
    <div>
      {fooSlider}
      <h1>{foo}</h1>
    </div>
  );
}

This avoids the pattern where you define const [state, setState] = useState(); at the top of a component then pass both the value and its setter to a child component like <Picker state={state} onChange={setState} />. But I’m a bit wary because it feels like the sort of thing that is convenient at the expense of composability.

What would you say if you saw this in a code review? I'd love to hear any thoughts on this — I'm @noahlt on Twitter or you can email me at hi@noahtye.com.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment