use ganchos ou HOC faça a sua escolha
Usando ganchos ou o padrão HOC (componente de ordem superior) , você pode ter atualizações automáticas quando suas lojas mudarem. Essa é uma abordagem muito leve, sem uma estrutura.
useStore Hooks para lidar com as atualizações da loja
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;
}
atualizações de armazenamento de manipulador do 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}
/>
);
}
};
};
}
Classe 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;
}
}
Como usar
No caso de ganchos:
// use inside function like so
const someState = useStore(myStore);
someState.myProp = 'something';
No caso do 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);
Certifique-se de
exportar suas lojas como um singleton para obter o benefício da mudança global da seguinte forma:
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};
Essa abordagem é bastante simples e funciona para mim. Também trabalho em grandes equipes, uso o Redux e o MobX e acho que eles também são bons, mas com bastante clichê. Pessoalmente, gosto da minha própria abordagem, porque sempre odiei muito código para algo que pode ser simples quando você precisa.
this.forceUpdate()
é a solução certa, enquanto o restante de todas as respostas e vários comentários são contra o usoforceUpdate()
. Será bom dizer que a pergunta ainda não obteve uma solução / resposta adequada?