One-line controlled and uncontrolled property binding for React
npm install use-binding
When developing React components, you often have to choose between providing a controlled (or "stateless") or uncontrolled ("stateful") version. For instance, if you have a custom Input component, do you:
- Provide a
defaultValueprop and manage the state inside your component (uncontrolled), or do you: - Provide a
valueprop and expect the parent component to manage state for you (controlled)?
You may end up developing both variants, adding lots of boilerplate code.
useBinding allows you to do both in one line.
Use this in your component:
const [myValue, setMyValue] = useBinding(
defaultValue,
value,
onChange,
fallbackValue /* optional */
);Now use myValue as your property value, and use setMyValue whenever you want to change it. Everything works as expected. That means:
- If the consumer of your component passes a
value, that value will be used. - If the consumer of your component passes a
defaultValue, thenuseBindingwill useuseStateinternally to keep track of the current value. - If both
defaultValueandvalueare empty, then thefallbackValuewill be used. ThefallbackValueis optional: if you don't provide it either, thenmyValuewill be null. - If the consumer of your component passed an
onChangehandler, that handler will be called when usingsetMyValue.
Consider the Input example above. You can use useBinding like this:
import React from 'react';
import { useBinding } from 'use-binding';
interface IInputProps {
defaultValue?: string
value?: string
onChange?: (newValue: string) => void
}
const CustomInput: React.FC<IInputProps> = ({ defaultValue, value, onChange }) => {
const [inputValue, setInputValue] = useBinding(defaultValue, value, onChange, '');
return (
<input type="text" value={inputValue} onChange={(e: ChangeEvent<HTMLInputElement>) => { setInputValue(e.target.value) })} />
);
};This will give consumers of your CustomInput component a lot of options:
// Controlled:
const [value, setValue] = useState('');
<CustomInput value={value} onChange={setValue} />;
// Uncontrolled:
<CustomInput defaultValue="my default" onChange={(newValue: string) => { console.log(newValue); })} />;
// Fixed value:
<CustomInput value="can't change me" />;useBinding supports Typescript and contains generic typings. Of course you can also use it in plain old Javascript.
Developed by Sebastiaan Besselsen at Sdu Uitgevers, The Netherlands.