используйте крючки или HOC выбирайте
Используя хуки или шаблон HOC (компонент более высокого порядка) , вы можете получать автоматические обновления при изменении ваших магазинов. Это очень легкий подход без фреймворка.
useStore Hooks способ обработки обновлений магазина
interface ISimpleStore {
on: (ev: string, fn: () => void) => void;
off: (ev: string, fn: () => void) => void;
}
export default function useStore<T extends ISimpleStore>(store: T) {
const [storeState, setStoreState] = useState({store});
useEffect(() => {
const onChange = () => {
setStoreState({store});
}
store.on('change', onChange);
return () => {
store.off('change', onChange);
}
}, []);
return storeState.store;
}
withStores Обновления хранилища дескрипторов HOC
export default function (...stores: SimpleStore[]) {
return function (WrappedComponent: React.ComponentType<any>) {
return class WithStore extends PureComponent<{}, {lastUpdated: number}> {
constructor(props: React.ComponentProps<any>) {
super(props);
this.state = {
lastUpdated: Date.now(),
};
this.stores = stores;
}
private stores?: SimpleStore[];
private onChange = () => {
this.setState({lastUpdated: Date.now()});
};
componentDidMount = () => {
this.stores &&
this.stores.forEach((store) => {
// each store has a common change event to subscribe to
store.on('change', this.onChange);
});
};
componentWillUnmount = () => {
this.stores &&
this.stores.forEach((store) => {
store.off('change', this.onChange);
});
};
render() {
return (
<WrappedComponent
lastUpdated={this.state.lastUpdated}
{...this.props}
/>
);
}
};
};
}
Класс SimpleStore
import AsyncStorage from '@react-native-community/async-storage';
import ee, {Emitter} from 'event-emitter';
interface SimpleStoreArgs {
key?: string;
defaultState?: {[key: string]: any};
}
export default class SimpleStore {
constructor({key, defaultState}: SimpleStoreArgs) {
if (key) {
this.key = key;
// hydrate here if you want w/ localState or AsyncStorage
}
if (defaultState) {
this._state = {...defaultState, loaded: false};
} else {
this._state = {loaded: true};
}
}
protected key: string = '';
protected _state: {[key: string]: any} = {};
protected eventEmitter: Emitter = ee({});
public setState(newState: {[key: string]: any}) {
this._state = {...this._state, ...newState};
this.eventEmitter.emit('change');
if (this.key) {
// store on client w/ localState or AsyncStorage
}
}
public get state() {
return this._state;
}
public on(ev: string, fn:() => void) {
this.eventEmitter.on(ev, fn);
}
public off(ev: string, fn:() => void) {
this.eventEmitter.off(ev, fn);
}
public get loaded(): boolean {
return !!this._state.loaded;
}
}
Как использовать
В случае крючков:
// use inside function like so
const someState = useStore(myStore);
someState.myProp = 'something';
В случае HOC:
// inside your code get/set your store and stuff just updates
const val = myStore.myProp;
myOtherStore.myProp = 'something';
// return your wrapped component like so
export default withStores(myStore)(MyComponent);
УБЕДИТЕСЬ
Чтобы экспортировать ваши магазины как одноэлементные, чтобы воспользоваться преимуществами глобальных изменений, например:
class MyStore extends SimpleStore {
public get someProp() {
return this._state.someProp || '';
}
public set someProp(value: string) {
this.setState({...this._state, someProp: value});
}
}
// this is a singleton
const myStore = new MyStore();
export {myStore};
Этот подход довольно прост и мне подходит. Я также работаю в больших командах и использую Redux и MobX, и считаю, что они тоже хороши, но представляют собой много шаблонов. Мне лично нравится мой собственный подход, потому что я всегда ненавидел много кода для чего-то, что может быть простым, когда вам это нужно.
в принятом ответе говорится, что
this.forceUpdate()
является правильным решением, тогда как остальные ответы и несколько комментариев против использованияforceUpdate()
. Можно ли тогда сказать, что вопрос еще не получил правильного решения / ответа?Исключенный ответ отвечал тогда на мой вопрос. Технически это тот ответ, который я искал, и я все еще думаю, что это правильный ответ. Другие ответы, я думаю, являются хорошей дополнительной информацией для людей, задающих тот же вопрос.
Интересно отметить, что вам вообще НИЧЕГО НЕ НУЖНО В СОСТОЯНИИ, кроме инициализации его простым объектом, а затем вызов this.setState ({}) просто запускает новый рендеринг. React - это здорово, но иногда и странно. Таким образом, вы можете напрямую перебирать данные хранилища при запуске изменения, не обращая внимания на данные для каждого экземпляра компонента.
В целом я бы сказал да. Если вы используете принудительное обновление, оно предназначено для обновления компонентов, где они могут зависеть от изменений вне управления состоянием вашего приложения. Я не могу придумать хороший пример этого. Хотя это полезно знать.