Использовать состояние или ссылки в компонентах формы React.js?
Я начинаю с React.js и хочу сделать простую форму, но в документации я нашел два способа сделать это.
Первый использует ссылки:
var CommentForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var author = React.findDOMNode(this.refs.author).value.trim();
var text = React.findDOMNode(this.refs.text).value.trim();
if (!text || !author) {
return;
}
// TODO: send request to the server
React.findDOMNode(this.refs.author).value = '';
React.findDOMNode(this.refs.text).value = '';
return;
},
render: function() {
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="Your name" ref="author" />
<input type="text" placeholder="Say something..." ref="text" />
<input type="submit" value="Post" />
</form>
);
}
});
И второй использует состояние внутри компонента React:
var TodoTextInput = React.createClass({
getInitialState: function() {
return {
value: this.props.value || ''
};
},
render: function() /*object*/ {
return (
<input className={this.props.className}
id={this.props.id}
placeholder={this.props.placeholder}
onBlur={this._save}
value={this.state.value}
/>
);
},
_save: function() {
this.props.onSave(this.state.value);
this.setState({value: ''
});
});
Я не вижу плюсов и минусов двух альтернатив, если таковые существуют. Благодарю.
3 ответа
Краткая версия: избегайте ссылок.
Они плохо подходят для сопровождения и теряют большую часть простоты визуализации модели WYSIWYG.
У вас есть форма. Вам нужно добавить кнопку, которая сбрасывает форму.
- рефов:
- манипулировать DOM
- render описывает, как форма выглядела 3 минуты назад
- государство
- SetState
- render описывает, как выглядит форма
У вас есть поле ввода номера CCV и некоторые другие поля в вашем приложении, которые являются числами. Теперь нужно принудительно вводить только пользовательские цифры.
- рефов:
- добавить обработчик onChange (разве мы не используем ссылки, чтобы избежать этого?)
- манипулировать домом в onChange, если это не число
- государство
- у вас уже есть обработчик onChange
- добавить оператор if, если он недействителен, ничего не делать
- рендер вызывается только в том случае, если он даст другой результат
Эх, неважно, премьер-министр хочет, чтобы мы просто сделали красную рамку-тень, если она недействительна.
- рефов:
- сделать обработчик onChange просто вызвать forceUpdate или что-то?
- сделать вывод рендеринга на основе... а?
- где мы получаем значение для проверки в рендере?
- вручную манипулировать свойством className dom элемента?
- я потерялся
- переписать без ссылок?
- читать из домена в рендере, если мы смонтированы, в противном случае допустим?
- государство:
- удалить оператор if
- сделать визуализацию валидной на основе this.state
Нам нужно вернуть контроль родителю. Данные теперь в реквизите, и мы должны реагировать на изменения.
- рефов:
- реализовать componentDidMount, componentWillUpdate и componentDidUpdate
- вручную разнести предыдущие реквизиты
- манипулировать домом с минимальным набором изменений
- Привет! мы реализуем реагировать в реагировать...
- это больше, но мои пальцы болят
- государство:
sed -e 's/this.state/this.props/' 's/handleChange/onChange/' -i form.js
Люди думают, что рефери "проще", чем держать их в состоянии. Это может быть правдой в течение первых 20 минут, это не так в моем опыте после этого. Поставьте себя в положение, чтобы сказать: "Да, я сделаю это через 5 минут", а не "Конечно, я просто перепишу несколько компонентов".
Я видел, как несколько человек цитировали приведенный выше ответ в качестве причины "никогда не использовать ссылки", и я хочу высказать свое (а также несколько других разработчиков React, с которыми я говорил).
Мнение "не использовать ссылки" является правильным, когда речь идет об использовании их для экземпляров компонентов. Это означает, что вы не должны использовать ссылки как способ захвата экземпляров компонентов и вызова методов для них. Это неправильный способ использовать ссылки, и они очень быстро уходят на юг.
Правильный (и очень полезный) способ использования ссылок - это когда вы используете их для получения некоторого значения из DOM. Например, если у вас есть поле ввода, присоединяющее ссылку к этому входу, тогда захват значения позже через ссылку просто подойдет. Без этого вам придется пройти довольно организованный процесс для обновления поля ввода в соответствии с вашим локальным состоянием или хранилищем потоков - что кажется ненужным.
Это старый пост
Я поделюсь своим небольшим опытом по одному делу по этому поводу.
Я работал над большим компонентом (414 строк) с множеством "динамических" входных данных и большим количеством задействованных кэшированных данных. (Я работаю над страницей не один, и мои чувства подсказывают мне, что структуру кода, вероятно, можно было бы разделить лучше, но дело не в этом (ну, может быть, но я имею дело с этим)
Сначала я работал с состоянием, чтобы обрабатывать значения входных данных:
const [inputsValues, setInputsValues] = useState([])
const setInputValue = (id, value) => {
const arr = [...inputsValues]
arr[id] = value
setInputsValues(arr)
}
и, конечно же, во входах:
value={inputsValues[id] || ''}
onChange={event => setInputValue(id, event.target.value)}
Рендеринг был настолько тяжелым, что изменение ввода было прерывистым, как **** (не пытайтесь удерживать клавишу нажатой, текст появится только после паузы)
Я был уверен, что смогу избежать этого, используя ссылки.
закончилось так:
const inputsRef = useRef([])
и во входах:
ref={input => (inputsRef.current[id] = input)}
[ну, в моем случае Input был Material-UI TextField, так что это было:
inputRef={input => (inputsRef.current[id] = input)}
]
Благодаря этому нет повторного рендеринга, ввод плавный, функциональность работает точно так же. Это сэкономит циклы и вычисления, а значит, и энергию. Сделайте это для земли x)
Мой вывод: может даже понадобиться useRef для значений input.
TL;DR Вообще говоря, refs
идти против декларативной философии React, поэтому вы должны использовать их в качестве последнего средства. использование state / props
когда возможно.
Чтобы понять, где вы используете refs
против state / props
Давайте рассмотрим некоторые принципы проектирования, которым придерживается React.
Per React документация о refs
Избегайте использования ссылок для всего, что может быть сделано декларативно.
Принципы разработки React о спасательных люках
Если какой-то шаблон, полезный для создания приложений, трудно выразить декларативным способом, мы предоставим для него обязательный API. (и они ссылаются на ссылки здесь)
Что означает, что команда React предлагает избежать refs
и использовать state / props
за все, что может быть сделано реактивным / декларативным способом.
@Tyler McGinnis дал очень хороший ответ, заявив также, что
Правильный (и очень полезный) способ использования ссылок - это когда вы используете их для получения некоторого значения из DOM...
Хотя вы можете сделать это, вы будете работать против философии React. Если у вас есть ценность на входе, это, безусловно, исходит от state / props
, Чтобы код был последовательным и предсказуемым, вы должны придерживаться state / props
там тоже. Я признаю тот факт, что refs
иногда дает вам более быстрое решение, поэтому, если вы делаете проверку концепции, приемлемо быстрое и грязное.
Это оставляет нам несколько конкретных вариантов использования для refs
Управление фокусом, выделением текста или воспроизведением мультимедиа. Запуск императивных анимаций. Интеграция со сторонними библиотеками DOM.