Я обнаружил, что есть несколько способов обработки пользовательского ввода текста с помощью хуков. Какой более предпочтительный или правильный способ обработки ввода с помощью хуков? Что бы вы использовали?
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}





Вот как я это делаю (при условии, что ваши входные данные должны быть внутри формы):
У меня есть компонент 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.info('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>
);
...
}
Как насчет того, чтобы написать повторно используемую функцию, которая возвращает входное значение... и саму <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}
</>;
не могли бы вы пролить больше света на синтаксис после возврата. Это кажется довольно новым для меня.
@JonathanAkweteyOkine, если вы говорите о втором возврате, это сокращенный синтаксис для фрагментов React. См. также здесь: reactjs.org/docs/fragments.html
@Марко, спасибо. Но синтаксис, о котором я говорил, это {userInput} -> {username}
Нужно ли использовать префикс use в функциях, не использующих хуки?
@NiyasNazar нет, не нужно. На самом деле это заблуждение.
@Marco Стрелка -> просто отображается как текст и не имеет особого синтаксиса.
@JonasWilms не будет ли это перепривязывать прослушиватель onChange при каждом вызове?
@duhaime да, будет. Этот фрагмент не «готов к копированию и вставке», он предназначен для демонстрации того, как можно использовать хуки в случае, приведенном на самом минимальном примере. Конечно, вы можете добавить useCallback, чтобы справиться с этим.
Пожалуйста, не делайте этого. HTML — это ценное общественное благо. Абстрагирование фундаментального веб-кирпичика в функцию, подобную этой, а затем затуманивание окон с помощью useState и деструктурирование ошеломят ваших менее изобретательных коллег и отрежут их от мира совершенства HTML. 100 голосов за этот ответ заставляют меня думать, что я не в той группе пингвинов.
Да, вы можете обрабатывать хуки реакции с помощью useState()
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.info(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}
/>
Собирался прокомментировать это. Это самый простой способ, который я чувствую. Кроме того, вот как Дэн Абрамов продемонстрировал это, вводя хуки здесь: youtube.com/watch?v=dpw9EHDh2bM @ 25:25
Это очень простой и органичный способ понять. Спасибо.
Однако вы должны обернуть onChangeHandler с useCallback.
почему @АндреасЛиннерт?
@ncesar Хорошо, обновленная информация: кажется, это не так просто. В этом случае простой вызов useCallback() требует больше производительности, чем экономит. Это полезно только в сочетании с дочерними компонентами, заключенными в React.memo().
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>
)
}
}
Вы не увидите упоминания об этом в документах React, но вы можете рассмотреть библиотеку форм, например Формик.
Это именно то, что упоминается в React Docs: reactjs.org/docs/forms.html#full-fledged-solutions.
useReduceболее гибкий и менее подверженный ошибкам, чемuseStateдля объектов