Использование mixins vs components для повторного использования кода в Facebook React
Я начинаю использовать Facebook React в базовом проекте, и до сих пор все идет очень хорошо.
Тем не менее, я заметил некоторое дублирование, ползущее в мой код реакции.
например, у меня есть несколько виджетов, подобных форме С такими состояниями, как INITIAL
, SENDING
и SENT
. При нажатии кнопки необходимо проверить форму, сделать запрос и обновить состояние. Состояние хранится внутри React this.state
конечно, вместе с полем ценности.
если бы это были базовые представления, я бы извлек базовый класс под названием FormView
но у меня сложилось впечатление, что React не одобряет и не поддерживает подклассы для обмена логикой просмотра (поправьте меня, если я ошибаюсь).
Я видел два подхода к повторному использованию кода в React:
- Mixins (как LinkedStateMixin что корабли с реагировать);
- компоненты контейнера (такие как react-infinite-scroll).
Я прав, что миксины и контейнеры предпочтительнее наследования в React? Это преднамеренное дизайнерское решение? имеет ли смысл использовать mixin или компонент контейнера для моего примера "виджета формы" из второго абзаца?
вот суть с FeedbackWidget
и JoinWidget
в их нынешнем состоянии. У них похожая структура, похожие beginSend
метод и оба будут нуждаться чтобы иметь некоторую поддержку проверки (еще нет).
2 ответов
Update: этот ответ устарел. Держись подальше от миксинов, если сможешь. Я тебя предупреждал!
Миксины Мертвы. Да Здравствует Композиция
сначала я попытался использовать подкомпоненты для этого и извлечь FormWidget
и InputWidget
. Однако я отказался от этого подхода на полпути, потому что хотел лучше контролировать сгенерированный input
S и их состояние.
две статьи, которые помогли мне большинство:
- мышление в React заставил меня понять, что я на самом деле не хочу вложенных компонентов для этого;
- Многоразовые Компоненты имеет аккуратный пример mixin.
оказалось, что мне нужно было написать только два (разных) миксина:ValidationMixin
и FormMixin
.
Вот как я их разделил.
ValidationMixin
Validation mixin добавляет удобные методы для запуска валидатора функции на некоторых свойствах вашего государства и хранят свойства "error'D" в state.errors
массив, чтобы вы могли выделить соответствующие поля.
источник (суть)
define(function () {
'use strict';
var _ = require('underscore');
var ValidationMixin = {
getInitialState: function () {
return {
errors: []
};
},
componentWillMount: function () {
this.assertValidatorsDefined();
},
assertValidatorsDefined: function () {
if (!this.validators) {
throw new Error('ValidatorMixin requires this.validators to be defined on the component.');
}
_.each(_.keys(this.validators), function (key) {
var validator = this.validators[key];
if (!_.has(this.state, key)) {
throw new Error('Key "' + key + '" is defined in this.validators but not present in initial state.');
}
if (!_.isFunction(validator)) {
throw new Error('Validator for key "' + key + '" is not a function.');
}
}, this);
},
hasError: function (key) {
return _.contains(this.state.errors, key);
},
resetError: function (key) {
this.setState({
'errors': _.without(this.state.errors, key)
});
},
validate: function () {
var errors = _.filter(_.keys(this.validators), function (key) {
var validator = this.validators[key],
value = this.state[key];
return !validator(value);
}, this);
this.setState({
'errors': errors
});
return _.isEmpty(errors);
}
};
return ValidationMixin;
});
использование
ValidationMixin
есть три способа: validate
, hasError
и resetError
.
Он ожидает, что класс определит
Я строю СПА с React (в производстве с 1 года), и я почти никогда не использую миксины.
единственный usecase у меня в настоящее время для mixins, когда вы хотите поделиться поведением, которое использует методы жизненного цикла React (componentDidMount
и т. д.). Эта проблема решается компонентами высшего порядка, о которых говорит Дан Абрамов в своем ссылке (или с помощью наследования класса ES6).
Mixins также часто используются в рамках, чтобы сделать framework API доступным для всех компоненты, используя "hidden"контекстный элемент реагирует. Это больше не понадобится с наследованием класса ES6.
В большинстве других случаев используются миксины, но на самом деле они не нужны и могут быть заменены простыми помощниками.
например:
var WithLink = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
return <input type="text" valueLink={this.linkState('message')} />;
}
});
вы можете очень легко рефакторинг LinkedStateMixin
код, чтобы синтаксис был:
var WithLink = React.createClass({
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
return <input type="text" valueLink={LinkState(this,'message')} />;
}
});
есть ли большая разница?