最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is there a generic way to set state in React Hooks? How to manage multiple states? - Stack Overflow

programmeradmin2浏览0评论

I have a question, if I can use useState generic in React Hooks, just like I can do this in React Components while managing multiple states?

state = {
  input1: "",
  input2: "",
  input3: ""
  // .. more states
};

handleChange = (event) => {
  const { name, value } = event.target;
  this.setState({
    [name]: value,
  });
};

I have a question, if I can use useState generic in React Hooks, just like I can do this in React Components while managing multiple states?

state = {
  input1: "",
  input2: "",
  input3: ""
  // .. more states
};

handleChange = (event) => {
  const { name, value } = event.target;
  this.setState({
    [name]: value,
  });
};
Share Improve this question edited Feb 11, 2021 at 10:39 Dennis Vash 53.9k11 gold badges116 silver badges132 bronze badges asked Jul 9, 2019 at 10:29 MateuszMateusz 952 gold badges2 silver badges7 bronze badges 3
  • Do you mean doing this with state variables? If you are using more plex state then obviously this can be done similar to how it's done in your class ponent example. For the former, see my answer which demonstrates the ability to set variable state in a dynamically. – James Commented Jul 9, 2019 at 10:39
  • @ravibagul91 not necessarily, you can manage plex state with useState – James Commented Jul 9, 2019 at 10:40
  • @James Yeah, that's what I'm looking for. I'll delve into your linked answer – Mateusz Commented Jul 9, 2019 at 10:48
Add a ment  | 

3 Answers 3

Reset to default 12

Yes, with hooks you can manage plex state (without 3rd party library) in three ways, where the main reasoning is managing state ids and their corresponding elements.

  1. Manage a single object with multiple states (notice that an array is an object).
  2. Use useReducer if (1) is too plex.
  3. Use multiple useState for every key-value pair (consider the readability and maintenance of it).

Check out this:

// Ids-values pairs.
const plexStateInitial = {
  input1: "",
  input2: "",
  input3: ""
  // .. more states
};

function reducer(state, action) {
  return { ...state, [action.type]: action.value };
}

export default function App() {
  const [fromUseState, setState] = useState(plexStateInitial);

  // handle generic state from useState
  const onChangeUseState = (e) => {
    const { name, value } = e.target;
    setState((prevState) => ({ ...prevState, [name]: value }));
  };

  const [fromReducer, dispatch] = useReducer(reducer, plexStateInitial);

  // handle generic state from useReducer
  const onChangeUseReducer = (e) => {
    const { name, value } = e.target;
    dispatch({ type: name, value });
  };
 
  return (
    <>
      <h3>useState</h3>
      <div>
        {Object.entries(fromUseState).map(([key, value]) => (
          <input
            key={key}
            name={key}
            value={value}
            onChange={onChangeUseState}
          />
        ))}
        <pre>{JSON.stringify(fromUseState, null, 2)}</pre>
      </div>

      <h3>useReducer</h3>
      <div>
        {Object.entries(fromReducer).map(([key, value]) => (
          <input
            name={key}
            key={key}
            value={value}
            onChange={onChangeUseReducer}
          />
        ))}
        <pre>{JSON.stringify(fromReducer, null, 2)}</pre>
      </div>
    </>
  );
}

Notes

  • Unlike the setState method found in class ponents, useState does not automatically merge update objects. You can replicate this behavior by bining the function updater form with object spread syntax:
setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

Refer to React Docs.

The correct way to do what you're trying to do is to create your own hook that uses useState internally.

Here is an example:

// This is your generic reusable hook.
const useHandleChange = (initial) => {
  const [value, setValue] = React.useState(initial);
  const handleChange = React.useCallback(
    (event) => setValue(event.target.value), // This is the meaty part.
    []
  );
  return [value, handleChange];
}

const App = () => {
  // Here we use the hook 3 times to show it's reusable.
  const [value1, handle1] = useHandleChange('one');
  const [value2, handle2] = useHandleChange('two');
  const [value3, handle3] = useHandleChange('three');
  return <div>
    <div>
      <input onChange={handle1} value={value1} />
      <input onChange={handle2} value={value2} />
      <input onChange={handle3} value={value3} />
    </div>
    <h2>States:</h2>
    <ul>
      <li>{value1}</li>
      <li>{value2}</li>
      <li>{value3}</li>
    </ul>
  </div>
}

ReactDOM.render(<App />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Note the use of React.useCallback to stop your hook from returning a new handler function on every render. (We don't need to specify setValue as a dependency because React guarantees that it will never change)

I didn't actually test this, but it should work.

See https://reactjs/docs/hooks-reference.html#usestate for more info.

import React, {useState} from 'react';

const MyComponent = () => {
    const [name, setName] = useState('Default value for name');
    return (<div><button onClick={()=>setName('John Doe')}}>Set Name</button></div>);
};
export default MyComponent;
发布评论

评论列表(0)

  1. 暂无评论