Примеры интеграции компонентов React с хранилищами MobX, которые я видел, кажутся тесно связанными. Я хотел бы сделать это более пригодным для повторного использования способом и был бы признателен за помощь в понимании «правильного» способа сделать это.
Я написал следующий код (React + MobX + Typescript), чтобы проиллюстрировать, что я хочу сделать, и проблему, с которой я столкнулся.
В магазине имеется несколько наблюдаемых временных отметок.
/***
* Initialize simple store
*/
class MyStore {
@observable value: number;
@action setValue(val: number) { this.value = val; }
@observable startTimestamp: number;
@action setStartTimestamp(val: number) { this.startTimestamp = val; }
@observable endTimestamp: number;
@action setEndTimestamp(val: number) { this.endTimestamp = val; }
}
Допустим, я хочу создать повторно используемый компонент ввода даты, позволяющий пользователю вводить дату либо для startTimestamp, endTimestamp, либо для какого-либо другого свойства магазина. В более общем смысле я хочу создать компонент, который можно использовать для изменения любого произвольного свойства любого магазина.
Мое лучшее понимание интеграции React / MobX состоит в том, что компоненты получают хранилище MobX, читают наблюдаемые свойства хранилища и могут выполнять действия для изменения этих свойств. Однако, похоже, это предполагает, что компоненты связаны с именами свойств магазина, что делает их не полностью пригодными для повторного использования.
Я экспериментировал со следующим подходом «хранилище прокси», чтобы выставить свойство, которое я хочу, компоненту как «значение»:
class MyStoreTimestampProxy {
constructor(private store: MyStore, private propertyName: 'startTimestamp' | 'endTimestamp') {
}
@observable get value() {
return this.store[this.propertyName];
}
@action setValue(val: number) {
this.store[this.propertyName] = val;
}
};
const myStoreStartTimestamp = new MyStoreTimestampProxy(myStore, 'startTimestamp');
const myStoreEndTimestamp = new MyStoreTimestampProxy(myStore, 'endTimestamp');
Тем не менее, я чувствую, что я как-то не так поступаю с React / MobX, и хочу понять здесь лучшие практики. Спасибо!
Полный код следует:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { observable, action } from 'mobx';
import { observer } from 'mobx-react';
/***
* Initialize simple store
*/
class MyStore {
@observable value: number;
@action setValue(val: number) { this.value = val; }
@observable startTimestamp: number;
@action setStartTimestamp(val: number) { this.startTimestamp = val; }
@observable endTimestamp: number;
@action setEndTimestamp(val: number) { this.endTimestamp = val; }
}
const myStore = new MyStore();
myStore.setValue(new Date().getTime());
/**
* My time input component. Takes in a label for display, and a store for reading/writing the property.
*/
interface IDateInputProps {
label: string;
store: {
value: number;
setValue(val: number): void;
}
}
interface IDateInputState {
value: string;
}
@observer class DateInput extends React.Component<IDateInputProps, IDateInputState> {
constructor(props: IDateInputProps) {
super(props);
this.state = { value: new Date(props.store.value).toDateString() };
}
render() {
return (
<div>
<label>{this.props.label}
<input
value={this.state.value}
onChange={this.onChange.bind(this)} />
</label>
</div>
);
}
onChange(event) {
const date = new Date(event.target.value);
this.setState({ value: event.target.value });
this.props.store.setValue(date.getTime());
}
}
/**
* Test view
*
*/
class TestView extends React.Component {
render() {
return (
<div>
<DateInput label="Editing the value property of store: " store={myStore}></DateInput>
{/* How to create components for startTimestamp and endTimestamp */}
</div>
);
}
};
ReactDOM.render(<TestView />, document.getElementById('root'));