使用 React 钩子处理输入

Handle an input with React hooks

我发现有几种方法可以使用钩子处理用户的文本输入。用钩子处理输入的更可取或正确的方法是什么?你会用哪个?

1) 最简单的hook来处理输入,但是你有更多的字段,你要写更多的重复代码。

const [username, setUsername] = useState('');
const [password, setPassword] = useState('');

事件:

onChange={event => setPassword(event.target.value)}
onChange={event => setUsername(event.target.value)}

2) 与上面的示例类似,但具有动态键名

const [inputValues, setInputValues] = useState({
  username: '', password: ''
});

const handleOnChange = event => {
  const { name, value } = event.target;
  setInputValues({ ...inputValues, [name]: value });
};

事件:

onChange={handleOnChange}

3) useState 的替代方案,如 ReactJS 文档所述,useReducer 通常优于 useState

const [inputValues, setInputValues] = useReducer(
  (state, newState) => ({ ...state, ...newState }),
  {username: '', password: ''}
);

const handleOnChange = event => {
  const { name, value } = event.target;
  setInputValues({ [name]: value });
};

事件:

onChange={handleOnChange}

4) useCallback 将 return 回调的记忆版本,仅当其中一个依赖项发生更改时才会更改。

const [inputValues, setInputValues] = useState({ 
  username: '', password: '' 
});

const handleOnChange = useCallback(event => {
  const { name, value } = event.target;
  setInputValues({ ...inputValues, [name]: value });
});

事件:

onChange={handleOnChange}

这是我的操作方法(假设您的输入必须在表单内):

我有一个我使用的 BasicForm 组件。

它将所有输入状态存储到一个对象中到单个 useState() 调用中。

它通过 useContext() 传递 inputs 状态以及一个 onChange() 函数和一个函数 setInputInitialState() 用于在首次安装时设置输入的初始状态.它还传递 onFocus、onBlur,并且它具有验证字段的功能,我没有在此处显示以简化代码。

通过这种方式,我可以轻松地创建一个包含任意数量输入的表单,例如:

<BasicForm
      isSubmitting={props.isSubmitting}
      submitAction={ (formState) =>
        props.doSignIn(formState) }
    >
      <TextInput
        type='email'
        label='Email'
        name='email'
        placeholder='Enter email...'
        required
      />
      <TextInput
        type='password'
        label='Password'
        name='password'
        placeholder='Enter password...'
        min={6}
        max={12}
        required
      />
      <SubmitButton
        label='Login'
      />
    </BasicForm>

BasicForm.js

import FormContext from './Parts/FormContext';

function BasicForm(props) {

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

  function onChange(event) {
    const newValue = event.target.value;
    const inputName = event.target.name;
    setInputs((prevState)=> {
      return({
        ...prevState,
        [inputName]: {
          ...prevState[inputName],
          value: newValue,
          dirty: true
        }
      });
    });
  }

  function setInputInitialState(
    inputName,
    label='This field ',
    type,
    initialValue = '',
    min = false,
    max = false,
    required = false) {

    const INITIAL_INPUT_STATE = {
      label: label,
      type: type,
      onFocus: false,
      touched: false,
      dirty: false,
      valid: false,
      invalid: false,
      invalidMsg: null,
      value: initialValue,
      min: min,
      max: max,
      required: required
    };

    setInputs((prevState) => {
      if (inputName in prevState) {
        return prevState;
      }
      return({
        ...prevState,
        [inputName]: INITIAL_INPUT_STATE
      });
    });

  }

return(
    <FormContext.Provider value={{
      onChange: onChange,
      inputs: inputs,
      setInputInitialState: setInputInitialState,
    }}>
      <form onSubmit={onSubmit} method='POST' noValidate>
        {props.children}
      </form>
    </FormContext.Provider>
  );
}

TextInput.js

输入使用 useEffect() 钩子来设置它们在安装时的初始状态。

function TextInput(props) {

  const formContext = useContext(FormContext);

  useEffect(() => {
    console.log('TextInput useEffect...');
    formContext.setInputInitialState(
      props.name,
      props.label,
      props.type,
      props.initialValue,
      props.min,
      props.max,
      props.required
    );
  },[]);

  return(
      <input
        type={props.type}
        id={props.name}
        name={props.name}
        placeholder={props.placeholder}
        value={([props.name] in formContext.inputs) ?
                  formContext.inputs[props.name].value
                : props.initialValue || ''}
        onChange={formContext.onChange}
        onFocus={formContext.onFocus}
        onBlur={formContext.onBlur}
      >
      </input>
      </div>
      {([props.name] in formContext.inputs) ?
          formContext.inputs[props.name].invalidMsg && <div><span> {formContext.inputs[props.name].invalidMsg}</span></div>
        : null}
    </div>
  );

...
}

写一个 returns 输入值 ... 和 <input> 本身的可重用函数怎么样:

 function useInput({ type /*...*/ }) {
   const [value, setValue] = useState("");
   const input = <input value={value} onChange={e => setValue(e.target.value)} type={type} />;
   return [value, input];
 }

然后可以用作:

 const [username, userInput] = useInput({ type: "text" });
 const [password, passwordInput] = useInput({ type: "text" });

 return <>
   {userInput} -> {username} <br />
   {passwordInput} -> {password}
 </>;

是的,您可以使用 useState() 处理 React Hooks

import React, {useState} from 'react'

export default () => {
    const [fName, setfName] = useState('');
    const [lName, setlName] = useState('');
    const [phone, setPhone] = useState('');
    const [email, setEmail] = useState('');

const submitValue = () => {
    const frmdetails = {
        'First Name' : fName,
        'Last Name' : lName,
        'Phone' : phone,
        'Email' : email
    }
    console.log(frmdetails);
}

return(
    <>
    <hr/>
    <input type="text" placeholder="First Name" onChange={e => setfName(e.target.value)} />
    <input type="text" placeholder="Last Name" onChange={e => setlName(e.target.value)} />
    <input type="text" placeholder="Phone" onChange={e => setPhone(e.target.value)} />
    <input type="text" placeholder="Email" onChange={e => setEmail(e.target.value)} />
    <button onClick={submitValue}>Submit</button>
    </>
    )
}

这就是我现在的使用方式:

const [inputValue, setInputValue] = React.useState("");

const onChangeHandler = event => {
   setInputValue(event.target.value);
};

<input
   type="text"
   name="name"
   onChange={onChangeHandler}
   value={inputValue}
/>
function App(){
    const [name, setName] = useState("");
    const [istrue, Setistrue] = useState(false);
    const [lastname,setLastname]=useState("");
    
    function handleclick(){
       Setistrue(true);
    }
    
    return(
        <div>
            {istrue ? <div> <h1>{name} {lastname}</h1> </div> : 
            <div>
                <input type="text" placeholder="firstname" name="name" onChange={e =>setName(e.target.value)}/>
                <input type="text" placeholder="lastname" name="lastname" onChange={e =>setLastname(e.target.value)}/>
               <button  type="submit" onClick={handleclick}>submit</button>
            </div>}
        </div>
    )
    
    }

}

您可能需要考虑像 Formik

这样的表单库