简体   繁体   English

如何用useState hook同时设置多个state?

[英]How to set several state at the same time with useState hook?

I would like to combine several states and handle them at the same time with useState hook, check the following example which updates some text on user input:我想结合几个状态并使用useState挂钩同时处理它们,检查以下示例,它更新了用户输入的一些文本:

 const {useState} = React; const Example = ({title}) => { const initialState = { name: 'John', age: 25 }; const [{name, age}, setFormState] = useState(initialState); const handleNameChange = (e) => { setFormState({ name: e.target.value, age }); }; const handleAgeChange = (e) => { setFormState({ name, age: e.target.value }) }; return ( <form onSubmit={e=>e.preventDefault()}> <input type='text' id='name' name='name' placeholder={name} onChange={handleNameChange} /> <p>The person's name is {name}.</p> <br /> <label htmlFor='age'>Age: </label> <input type='text' id='age' name='age' placeholder={age} onChange={handleAgeChange} /> <p>His/her age is {age}.</p> </form> ); }; // Render it ReactDOM.render( <Example />, document.getElementById("react") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="react"></div>

The code works well, but as you can see I'm using 2 functions to handle name and age separately., which was against my intention to save some code.代码运行良好,但如您所见,我使用了 2 个函数来分别处理姓名和年龄,这违背了我保存一些代码的意图。 Is it possible to just use 1 function to change name and age separately?是否可以只使用 1 function 分别更改姓名和年龄? Tried this but obviously it would update both with the same value.试过了,但显然它会用相同的值更新两者。

 const {useState} = React; const Example = ({title}) => { const initialState = { name: 'John', age: 25 }; const [{name, age}, setFormState] = useState(initialState); const handleChange = (e) => { setFormState({ name: e.target.value, age: e.target.value }); }; return ( <form onSubmit={e=>e.preventDefault()}> <input type='text' id='name' name='name' placeholder={name} onChange={handleChange} /> <p>The person's name is {name}.</p> <br /> <label htmlFor='age'>Age: </label> <input type='text' id='age' name='age' placeholder={age} onChange={handleChange} /> <p>His/her age is {age}.</p> </form> ); }; // Render it ReactDOM.render( <Example />, document.getElementById("react") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="react"></div>

It's not possible to set several different states at the same time with a single useState hook.不可能使用单个 useState 挂钩同时设置多个不同的状态。 You can either set them separately, example:您可以单独设置它们,例如:

const [userName, setUserName] = useState('');
const [password, setPassword] = useState('');

or put all of the states into an object, and update that object using the useState hook.或者将所有状态放入 object,并使用 useState 挂钩更新该 object。 Source: https://daveceddia.com/usestate-hook-examples/ Example:来源: https://daveceddia.com/usestate-hook-examples/示例:

const [form, setState] = useState({
  username: '',
  password: ''
});

const updateField = e => {
    setState({
      ...form,
      [e.target.name]: e.target.value
    });
  };

return (
    <form onSubmit={printValues}>
      <label>
        Username:
        <input
          value={form.username}
          name="username"
          onChange={updateField}
        />
      </label>
      <br />
      <label>
        Password:
        <input
          value={form.password}
          name="password"
          type="password"
          onChange={updateField}
        />
      </label>
      <br />
      <button>Submit</button>
    </form>
  );

You have a couple options to get your intended effect.你有几个选项来获得你想要的效果。

You could, for example, make a single function factory.例如,您可以创建一个 function 工厂。

 const {useState} = React; const Example = ({title}) => { const initialState = { name: 'John', age: 25 }; const [{name, age}, setFormState] = useState(initialState); const handleChange = key => e => { const newValue = e.target.value setFormState(oldState => ({...oldState, [key]: newValue })); }; return ( <form onSubmit={e=>e.preventDefault()}> <input type='text' id='name' name='name' placeholder={name} onChange={handleChange('name')} /> <p>The person's name is {name}.</p> <br /> <label htmlFor='age'>Age: </label> <input type='text' id='age' name='age' placeholder={age} onChange={handleChange('age')} /> <p>His/her age is {age}.</p> </form> ); }; // Render it ReactDOM.render( <Example />, document.getElementById("react") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="react"></div>

Alternatively, if you need a function factory with more flexibility (eg if you were trying to store other state in there), you could use useReducer() instead of useState(), then curry the dispatch function. As a rough, untested example或者,如果您需要一个具有更大灵活性的 function 工厂(例如,如果您试图在其中存储其他 state),您可以使用 useReducer() 而不是 useState(),然后 curry 调度 function。作为一个粗略的、未经测试的示例

const reducer = (state, {type, payload}) => {
  switch (type) {
    case 'name': return {...state, name: payload}
    case 'age': return {...state, age: payload}
    default: throw new Error()
  }
}

const [{name, age}, dispatch] = useReducer(reducer, { name: 'john', age: 25 })
const makeEventListener = type => e => dispatch({type, payload: e.target.value})
// Now, you can use either use makeEventListener, or dispatch() directly
return <input type="text" value={name} onChange={makeEventListener('name'))

Lastly, it is possible to do exactly what you're saying, have one function that'll just update the state no matter who called it, by using of refs.最后,可以完全按照您所说的去做,拥有一个 function,无论是谁调用它,它都会更新 state,通过使用 refs。 But this is not a recommended approach.但这不是推荐的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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