import * as React from 'react';
import { render } from 'react-dom';
// List of supported HTML elements
type ModelElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
// Custom hook for two-way data binding
// We can provide the initial value and an onChange function
// if we need to do additional things in our component
function useModel<E extends ModelElement>(
initial: string = null,
onChange?: React.ChangeEventHandler<E>
) {
const [value, setValue] = React.useState<string>(initial);
const handler: React.ChangeEventHandler<E> = (e) => {
// Store the current value and run the callback function if provided
setValue(e.currentTarget.value);
onChange && onChange(e);
};
const model = { value, onChange: handler };
return { model, setModel: setValue };
}
function App() {
// Use custom hook
const { model, setModel } = useModel('John', (e) => {
console.log('Model changed', e.currentTarget.value);
});
const reset = () => setModel('');
return (
<React.Fragment>
{/* Spread the model on the input element */}
<label htmlFor="name">Name: </label>
<input id="name" {...model} />
<div>Hello {model.value}</div>
<button onClick={reset}>Reset</button>
</React.Fragment>
);
}
render(<App />, document.getElementById('root'));
No comments:
Post a Comment