Обработка ввода с помощью React-хуков - PullRequest
2 голосов
/ 19 апреля 2019

Я обнаружил, что есть несколько способов обработать ввод текста пользователем с помощью хуков. Что является более предпочтительным или правильным способом обработки ввода с помощью хуков? Что бы вы использовали?

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}

Ответы [ 2 ]

0 голосов
/ 23 апреля 2019

Как насчет написания многократно используемой функции, которая возвращает входное значение ... и самого себя:

 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}
 </>;
0 голосов
/ 19 апреля 2019

Вот как я это делаю (при условии, что ваши входные данные должны быть внутри формы):

У меня есть компонент 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>
  );

...
}
...