使用 React 钩子处理输入

IT技术 reactjs react-hooks
2021-04-05 22:41:48

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

1) 处理输入的最简单的钩子,但是你有更多的字段,你必须编写更多重复的代码。

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将返回回调的记忆版本,该版本仅在依赖项之一发生更改时才会更改。

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

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

事件:

onChange={handleOnChange}
6个回答

如何编写一个可重用的函数来返回输入值......及其<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}
 </>;
您能否在返回后对语法进行更多说明。这对我来说似乎很新。
2021-05-27 22:41:48
@JonathanAkweteyOkine 如果您在谈论第二次返回,那是 React Fragments 的速记语法。另见此处:reactjs.org/docs/fragments.html
2021-05-27 22:41:48
@Marco -> 箭头只是呈现为文本,并不是任何特殊的语法。
2021-06-09 22:41:48
@JonasWilms 不会在每次调用时重新绑定 onChange 侦听器吗?
2021-06-18 22:41:48
@duhaime 是的,会的。此代码段不是“准备好复制和粘贴”,它旨在演示如何在给出的最小示例的情况下使用钩子。当然你可以添加一个useCallback来处理这个。
2021-06-21 22:41:48

是的,您可以使用 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}
      />
正要评论这个。这是我感觉最简单的方式。此外,这是 Dan Abramov 在此处介绍钩子时演示的方式:youtube.com/watch? v=dpw9EHDh2bM @ 25:25
2021-06-02 22:41:48
为什么@AndreasLinnert?
2021-06-04 22:41:48
@ncesar 好的,更新一下:似乎没那么简单。useCallback()在这种情况下,只是调用成本高于节省的性能。它仅与包装在React.memo().
2021-06-06 22:41:48
你应该onChangeHandleruseCallback虽然包装
2021-06-11 22:41:48
这是非常简单和有机的理解方式。谢谢。
2021-06-18 22:41:48

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

我有一个我使用的 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>

基本表单.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>
  );
}

文本输入.js

inputse 在挂载时使用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>
  );

...
}
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>
    )
    
    }

}