Сначала немного фона:
В процессе обучения реагируют и редуцируют, используя Typescript. Для компонентов с некоторым типом состояния приложения (а не состояния чистого пользовательского интерфейса) я пытаюсь сохранить логическое разделение между компонентами реагирования и базовой логикой и состоянием. С этой целью для компонентов, которые каким-то образом работают с данными состояния приложения, я реализовал класс ViewModel, который устанавливается на подпорки компонента и содержит свойства и действия, которые инкапсулируют поведение этих компонентов. Таким образом, ViewModel будет (например) извлекать данные из серверной части и представлять ее свойства компоненту реакции.
Одной из причин реализации этого разделения является обеспечение возможности модульного тестирования ViewModel независимо от чисто связанных аспектов View, содержащихся в компоненте реагирования. Я чувствую, что это важно как для первоначальной реализации, так и в будущем, если логика должна быть повторно реализована в какой-то будущей архитектуре - так что она остается понятной и самодостаточной без набора «проводки» для реакции, избыточности или моба. специфическая архитектура.
Я реализовал это с помощью mobx (декораторы @observable и @action в ViewModel, привязанные к компоненту, украшенному @observer). Все состояние, которое я реализую до сих пор таким образом, просто находится внутри компонента или передается дочерним компонентам с помощью иерархии ViewModel. Пока он работает очень хорошо, и это шаблон, который легко применить к новым компонентам, и он не станет огромным скачком для разработчиков, знакомых с нокаутом и т. Д., Что положительно сказывается на моей текущей ситуации.
Тем не менее, я сейчас ищу работу с некоторым состоянием, которое хранится глобально, чтобы его можно было разделить между компонентами и сохранить. Я расследовал, используя для этого редукционный магазин. Я действительно не хочу «выбросить ребенка с водой из ванны», и я хотел бы продолжать использовать mobx для «локального» состояния приложения и хочу сохранить разделение ViewModel по причинам, изложенным ранее.
Подход, который я реализовал до сих пор, состоит в том, чтобы создавать свойства состояния редукса как поля @observable, как обычно в моем классе ViewModel, с помощью декоратора @observable. Затем я подписываюсь на изменения состояния магазина из резервной копии (вызывая store.subscribe ()). Когда обратный вызов передается для запуска подписки (в методе действия mobx), я устанавливаю значение полей @observable в ViewModel значением, полученным из состояния. Mobx достаточно умен, чтобы выполнять повторную визуализацию только в том случае, если значение, установленное в состоянии, действительно изменилось.
Когда компонент, использующий ViewModel, запускает componentWillUnmount, я вызываю unsubscribe (), чтобы избежать сохранения большого количества подписок, когда они не требуются.
Так что мой класс ViewModel выглядит примерно так (просто набросок кода здесь):
import { Unsubscribe } from "redux";
class ViewModel {
@observable
public fieldFromReduxState: string | null = null;
private _unsubscribe: Unsubscribe | null = null;
// Called by the containing component in componentDidMount
public attach() {
this._unsubscribe = store.subscribe(this._updateFromState);
// Initial update from state
this._updateFromState();
}
// Called by the containing component in componentWillUnmount
public detach() {
if (this._unsubscribe) {
this._unsubscribe();
this._unsubscribe = null;
}
}
@action.bound
private _updateFromState() {
const state = store.getState();
// Update local field from state
this.fieldFromReduxState = state.myreducer.statevalue;
}
}
и компоненты, использующие модель представления, выглядят примерно так (опять же, просто набросок кода):
interface IMyComponentProps {
viewModel: ViewModel;
}
@observer
class MyView extends React.Component<IMyComponentProps> {
public static defaultProps = {
viewModel: new ViewModel()
}
public componentDidMount() {
this.props.viewModel.attach();
}
public componentWillUnmount() {
if (this.props.viewModel) {
this.props.viewModel.detach();
}
}
// In render, use this.props.viewModel.fieldName
// Bind events to viewModel methods
// In this way, the component retains just the pure view functionality
// and the ViewModel can be tested / re-used in isolation from react
...
}
То, что я ищу, - это понимание / совет для тех, кто имеет гораздо больший опыт работы с MOBX, реагирует и редукцирует относительно того, могу ли я столкнуться с проблемами в этой реализации или пропустил что-то ключевое. Я прекрасно осознаю, что все это довольно ново для меня, и я мог бы создать некоторые неприятные проблемы для себя. Мне также было бы очень интересно узнать, придумал ли кто-нибудь еще хорошие шаблоны для использования mobx вместе с redux для различных сценариев состояния в одном и том же проекте или даже компоненте. Мне кажется, это дает лучшее из обоих миров с выбором того, где должно жить государство.
Мне известно, что идея переноса логики из компонента в отдельный класс ViewModel не будет предпочтительным подходом для всех, поэтому, пожалуйста, расскажите мне немного об этом, если можете.
Мне также известно, что многие выступают за реализацию каждого отдельного изменения состояния (включая результаты переходных выборок данных из серверной части) в Redux с использованием действий и редукторов, но я действительно не заинтересован в том, чтобы идти по этому пути для компонентов без необходимости общего состояния; Модель mobx очень проста в работе, особенно для разработчиков, которые не имеют большого опыта работы с концепциями избыточности, когда основа кода переносится с более ранних технологий, таких как knockoutjs, или существует общее представление о шаблоне MVVM.
Итак, в общем, я в первую очередь ищу любые указатели на подводные камни и проблемы, к которым мой описанный подход может привести меня, и любые советы о том, как я мог бы их устранить, если это возможно.
Извините за длительность преамбулы и большое спасибо заранее за любую помощь или совет.