#reactjs #react-native #react-hooks
#язык JavaScript #реагирует на #реагируют-крючки
Вопрос:
У меня есть вопрос, могу ли я использовать useState
generic в крючках React, точно так же, как я могу это сделать в компонентах React, управляя несколькими состояниями?
state = { input1: "", input2: "", input3: "" // .. more states};handleChange = (event) =gt; { const { name, value } = event.target; this.setState({ [name]: value, });};
Комментарии:
1. Вы имеете в виду, что делаете это с переменными состояния? Если вы используете более сложное состояние, то, очевидно, это можно сделать аналогично тому, как это делается в примере компонента класса. Что касается первого, см. Мой ответ , который демонстрирует возможность динамически задавать состояние переменной.
2. @ravibagul91 не обязательно, вы можете управлять сложным состоянием с помощью
useState
3. @Джеймс Да, это то, что я ищу. Я углублюсь в ваш связанный ответ
Ответ №1:
Да, с помощью крючков вы можете управлять сложным состоянием (без сторонней библиотеки) тремя способами, где основным аргументом является управление идентификаторами состояний и их соответствующими элементами.
- Управляйте одним объектом с несколькими состояниями (обратите внимание, что массив является объектом).
- Используйте
useReducer
if (1
) слишком сложно. - Используйте несколько
useState
для каждой пары ключ-значение (учитывайте удобочитаемость и ее обслуживание).
Проверьте это:
// Ids-values pairs.const complexStateInitial = { input1: "", input2: "", input3: "" // .. more states};function reducer(state, action) { return { ...state, [action.type]: action.value };}export default function App() { const [fromUseState, setState] = useState(complexStateInitial); // handle generic state from useState const onChangeUseState = (e) =gt; { const { name, value } = e.target; setState((prevState) =gt; ({ ...prevState, [name]: value })); }; const [fromReducer, dispatch] = useReducer(reducer, complexStateInitial); // handle generic state from useReducer const onChangeUseReducer = (e) =gt; { const { name, value } = e.target; dispatch({ type: name, value }); }; return ( lt;gt; lt;h3gt;useStatelt;/h3gt; lt;divgt; {Object.entries(fromUseState).map(([key, value]) =gt; ( lt;input key={key} name={key} value={value} onChange={onChangeUseState} /gt; ))} lt;pregt;{JSON.stringify(fromUseState, null, 2)}lt;/pregt; lt;/divgt; lt;h3gt;useReducerlt;/h3gt; lt;divgt; {Object.entries(fromReducer).map(([key, value]) =gt; ( lt;input name={key} key={key} value={value} onChange={onChangeUseReducer} /gt; ))} lt;pregt;{JSON.stringify(fromReducer, null, 2)}lt;/pregt; lt;/divgt; lt;/gt; );}
Примечания
- В отличие от
setState
метода, найденного в компонентах класса,useState
не выполняет автоматическое объединение объектов обновления. Вы можете повторить это поведение, объединив форму средства обновления функций с синтаксисом распространения объектов:
setState(prevState =gt; { // Object.assign would also work return {...prevState, ...updatedValues};});
Обратитесь к документам React.
Комментарии:
1. При этом не используются крючки react.
2. Это правильно, но не так, как это можно сделать с помощью крючков реакции.
3.
setState
происходит отuseState
:const [state, setState] = useState(initialState);
4. @DennisVash: Я приношу свои извинения. Вы правы. Я не видел вашего объявления setState и предположил, что это тот же метод setState класса, о котором, похоже, спрашивал OP. Путаница для меня заключалась в том, что вы использовали одно и то же название метода.
5. @Джеймс: Не пытаюсь быть самонадеянным. Я думаю, мы действительно согласны. Ваш пользовательский ответ на крючок, в конечном счете, вероятно, будет тем ответом, который ищет ОП.
Ответ №2:
Правильный способ сделать то, что вы пытаетесь сделать, — это создать свой собственный крючок, который используется useState
внутри.
Вот пример:
// This is your generic reusable hook.const useHandleChange = (initial) =gt; { const [value, setValue] = React.useState(initial); const handleChange = React.useCallback( (event) =gt; setValue(event.target.value), // This is the meaty part. [] ); return [value, handleChange];}const App = () =gt; { // Here we use the hook 3 times to show it's reusable. const [value1, handle1] = useHandleChange('one'); const [value2, handle2] = useHandleChange('two'); const [value3, handle3] = useHandleChange('three'); return lt;divgt; lt;divgt; lt;input onChange={handle1} value={value1} /gt; lt;input onChange={handle2} value={value2} /gt; lt;input onChange={handle3} value={value3} /gt; lt;/divgt; lt;h2gt;States:lt;/h2gt; lt;ulgt; lt;ligt;{value1}lt;/ligt; lt;ligt;{value2}lt;/ligt; lt;ligt;{value3}lt;/ligt; lt;/ulgt; lt;/divgt;}ReactDOM.render(lt;App /gt;, document.querySelector("#app"))
lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"gt;lt;/scriptgt;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"gt;lt;/scriptgt;lt;div id="app"gt;lt;/divgt;
Обратите внимание на использование React.useCallback, чтобы ваш хук не возвращал новую функцию обработчика при каждом рендеринге. (Нам не нужно указывать setValue
в качестве зависимости, потому что React гарантирует, что она никогда не изменится)
Ответ №3:
На самом деле я это не проверял, но это должно сработать.
Видишь https://reactjs.org/docs/hooks-reference.html#usestate для получения дополнительной информации.
import React, {useState} from 'react';const MyComponent = () =gt; { const [name, setName] = useState('Default value for name'); return (lt;divgt;lt;button onClick={()=gt;setName('John Doe')}}gt;Set Namelt;/buttongt;lt;/divgt;);};export default MyComponent;
Комментарии:
1. Я не понимаю, как это отвечает на вопрос? Вы только что привели пример того , как использовать
setState
, как ОП выводит из этого, как установить его динамически?