简体   繁体   中英

Reusing state in React with Hooks

I see myself using declarations like:

const [state, setState] = React.useState({value: ''});
    
return <InputComponent {...properties} value={state.value} onChange={(event) => setState({value: event.target.value || event.target.checked}

Whenever a component needs state I have to rewrite this down and it feels not reusable at all. I looked for render props and HOC, but couldn't reuse state.

I tried creating:

const StatefulInput = (InputComponent) => {

  const [state, setState] = React.useState({value: ''});

  return <InputComponent value={state.value} onChange={(event) => setState({value: event.target.value || event.target.checked />
}

But I couldn't reuse, I got 'invalid Hook', 'render received object not something else' errors and some other ones.

How can I do it? Is it possible to reuse this hook?

To avoid the boilerplate, you can write a custom hook that holds the state, returning a value and a handler that you can pass to the child component:

 const InputComponent = ({ value, onChange }) => <input {...{value, onChange}} />; const useInputValue = (initialValue) => { const [value, setValue] = React.useState(initialValue); return [ value, event => setValue(event.target.value || event.target.checked) ]; }; const App = () => { const [inputValue, inputHandler] = useInputValue(''); return <InputComponent value={inputValue} onChange={inputHandler} /> }; ReactDOM.render(<App />, document.querySelector('.react'));
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div class="react"></div>

Or, have the custom hook return an object that can be spread into the child component:

 const InputComponent = ({ value, onChange }) => <input {...{value, onChange}} />; const useInputValue = (initialValue) => { const [value, setValue] = React.useState(initialValue); return { value, onChange: event => setValue(event.target.value || event.target.checked) }; }; const App = () => { const inputProps = useInputValue(''); return <InputComponent {...inputProps} /> }; ReactDOM.render(<App />, document.querySelector('.react'));
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div class="react"></div>

Also note that there's no need for the stateful value in useState to be an object - here, since all you need to store is a string (the current value), you can have the state be just that string , rather than wrapping the string in an object unnecessarily.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM