React Hooks:处理多个输入

IT技术 javascript reactjs react-hooks
2021-05-13 08:10:50

react docs forms 部分,有以下使用类组件的示例:

class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}

考虑到 Hooks 只能在 React 函数组件或自定义 React Hook 函数中调用,有没有办法使用钩子来代替?

4个回答

例子

const MyComponent = () => {
   const [inputs,setInputs] = useState({});

   return (
     <> 
      <input key="field1" name="field1" onChange={({target}) => setInputs(state => ({...state,field1:target.value}))} value={inputs.field1}/>
      <input key="field2" name="field2" onChange={({target}) => setInputs(state => ({...state,field2:target.value}))} value={inputs.field2}/>
     </>
   )

}

您可以像这样传入初始值:

const MyComponent = (initialValues = {}) => {
   const [inputs,setInputs] = useState(initialValues);
   ...
}

编辑:onChange根据@hamidreza评论,一个不错的短片

const MyComponent = (initialValues = {}) => {
   const [inputs,setInputs] = useState(initialValues);
   const onChangeHandler = useCallback(
     ({target:{name,value}}) => setInputs(state => ({ ...state, [name]:value }), [])
   );

   return (
     <> 
      <input key="field1" name="field1" onChange={onChangeHandler} value={inputs.field1}/>
      <input key="field2" name="field2" onChange={onChangeHandler} value={inputs.field2}/>
     </>
   )


}

等等等等等等

您可以通过不使用 useCallback 钩子,而是简单地使用 useState 钩子作为受控组件来清理@adam 的最终解决方案。

const MyComponent = () => {
   const [inputs, setInputs] = useState({});
   const handleChange = e => setInputs(prevState => ({ ...prevState, [e.target.name]: e.target.value }));

   return (
     <> 
      <input name="field1" value={inputs.field1 || ''} onChange={handleChange} />
      <input name="field2" value={inputs.field2 || ''} onChange={handleChange} />
     </>
   )
}

也许,在最后一个例子中 onChangeForField('...') 将在每次渲染时触发,所以也许你必须写 onChange={()=>onChangeForField('...')} 或者如果你想让事件通过 onChange={(e)=>onChangeForField('...', e)}

添加到亚当的答案以及那些正在寻找typescript解决方案的人,

interface MyIType {
    field1: string;
    ...
}

//Partial from typescript to make properties optional
interface MyFormType extends Partial<MyIType> {}

const [inputs,setInputs] = useState<MyFormType>(initialValues);
    
const onChangeForField = useCallback(({target}) => 
    setInputs(_state => {
            return {
                ..._state,
                [target.name]: target.value,
            };
        }),
    []
);