Это может быть переходом на границу между ответственным и самоуверенным, но я возвращаюсь взад и вперед относительно того, как структурировать компонент ReactJS по мере роста сложности и можно использовать какое-то направление.
Исходя из AngularJS, я хочу передать свою модель компоненту в качестве свойства и заставить компонент напрямую изменять модель. Или мне следует разбить модель на различные state
свойства и скомпилировать ее вместе при отправке обратно вверх по течению? Что такое ReactJS?
Возьмем, к примеру, редактор сообщений в блоге. Попытка изменить модель напрямую заканчивается так:
var PostEditor = React.createClass({
updateText: function(e) {
var text = e.target.value;
this.props.post.text = text;
this.forceUpdate();
},
render: function() {
return (
<input value={this.props.post.text} onChange={this.updateText}/>
<button onClick={this.props.post.save}/>Save</button>
);
}
});
Что кажется неправильным.
Это больше способ React создать text
свойство модели state
и скомпилировать его обратно в модель перед сохранением, например:
var PostEditor = React.createClass({
getInitialState: function() {
return {
text: ""
};
},
componentWillMount: function() {
this.setState({
text: this.props.post.text
});
},
updateText: function(e) {
this.setState({
text: e.target.value
});
},
savePost: function() {
this.props.post.text = this.state.text;
this.props.post.save();
},
render: function() {
return (
<input value={this.state.text} onChange={this.updateText}/>
<button onClick={this.savePost}/>Save</button>
);
}
});
Для этого не требуется вызова this.forceUpdate()
, но по мере роста модели (сообщение может иметь автора, тему, теги, комментарии, рейтинги и т. Д.) Компонент начинает усложняться.
text
поля у нас естьsetText
метод, который выполняет проверку и некоторые другие вещи. Я вижу, что метод (2) работает, еслиsetText
он чистый и возвращает новый экземпляр модели. Однако, если бы мыsetText
просто обновили внутреннее состояние, нам все равно нужно было бы вызватьforceUpdate
, верно?forceUpdate
, но в этот момент вы «утекаете» из React. Возможно, лучше передатьsetState()
обратный вызов непрозрачной модели, чтобы избежать необходимости вручную запускать повторный рендеринг.Обновление 2016: React изменен, и объяснение «props vs state» стало очень простым. Если компоненту нужно изменить данные - поместите его в состояние, иначе в props. Потому что теперь реквизиты доступны только для чтения .
В чем точная разница между реквизитом и состоянием?
Вы можете найти хорошее объяснение здесь (полная версия)
источник
setProps
устарела и не должна использоваться. Замена заключается в том, чтобы повторно отрендерить компонент и позволить React обработать различия.Из документа React
Из TrySpace : когда реквизиты (или состояние) обновляются (через setProps / setState или parent), компонент также перерисовывается.
источник
Чтение из книги Thinking in React :
источник
Я не уверен, отвечу ли я на ваш вопрос, но я обнаружил, что, особенно в большом / растущем приложении, шаблон "Контейнер / Компонент" работает невероятно хорошо.
По сути, у вас есть два компонента React:
пример
NB. Этот пример, вероятно, слишком прост, чтобы проиллюстрировать преимущества этого шаблона, поскольку он довольно многословен для такого простого случая.
Преимущества
Разделяя логику отображения и управление данными / состоянием, вы получаете повторно используемый компонент отображения, который:
У вас также есть компонент-контейнер, который занимается всей внешней связью. Это должно упростить гибкость при доступе к данным, если впоследствии вы внесете какие-либо серьезные изменения *.
Этот шаблон также значительно упрощает написание и реализацию модульных тестов.
Пройдя несколько итераций в большом приложении React, я обнаружил, что этот шаблон делает вещи относительно безболезненными, особенно когда у вас есть более крупные компоненты с рассчитанными стилями или сложными взаимодействиями с DOM.
* Прочтите о шаблоне потока и взгляните на
Marty.js , который во многом вдохновил этот ответ (а в последнее время я много использовал)Redux (и react-redux ), которые очень хорошо реализуют этот шаблон.источник
Я думаю, вы используете антипаттерн, который Facebook уже объяснил по этой ссылке.
Вот что вы обнаружите:
При первом рендеринге внутреннего компонента он будет иметь значение {foo: 'bar'} как свойство value. Если пользователь нажимает на якорь, состояние родительского компонента будет обновлено до {value: {foo: 'barbar'}}, запустив процесс повторной визуализации внутреннего компонента, который получит {foo: 'barbar'} как новое значение для опоры.
Проблема в том, что, поскольку родительский и внутренний компоненты используют ссылку на один и тот же объект, когда объект изменяется в строке 2 функции onClick, опора внутреннего компонента изменится. Итак, когда начинается процесс повторного рендеринга и вызывается shouldComponentUpdate, this.props.value.foo будет равно nextProps.value.foo, потому что на самом деле this.props.value ссылается на тот же объект, что и nextProps.value.
Следовательно, поскольку мы пропустим изменение в реквизите и закроем процесс повторного рендеринга, пользовательский интерфейс не будет обновляться с 'bar' на 'barbar'.
источник
Innercomponents
код?