Recently I wrote a business project, the existing code is MOBx + React Class, just want to use React Hook, so I made the following modifications to implement support
Code responsibility
- Store is responsible for storing business data definitions
- Action is responsible for manipulating data in the store
- Component uses actions to manipulate data, uses Store data to display content, and state is responsible for UI interaction state
Existing code
Provider
import { Provider } from 'mobx-react';
export class ContainerProvider extends React.Component<any.any> {
private injects: {
[injectName: string]: any
} = {};
UNSAFE_componentWillMount() {
const instances = injectInstance(
assign({}, this.props.inject)
);
// Complex apps can do some initialization here
this.injects = {};
instances.forEach((value, key) = > {
this.injects[key] = value;
});
}
render() {
return (
<Provider {. this.injects} >
{this.props.children}
</Provider>); }}Copy the code
inject
export const injectDecorator = (injectName: string): any => (target: any, propertyKey: string, descriptor: PropertyDescriptor): any => { target[propertyKey] = injectName; // add an annotation variable if (! target['_injectVariables_']) { target['_injectVariables_'] = [propertyKey]; } else { target['_injectVariables_'].push(propertyKey); } return descriptor; }; export const injectInstance = (classes: {}) => { const classMap = new Map<string, any>(); const instanceMap = new Map<string, any>(); ForEach ((eachClassName) => {if (classmap. has(eachClassName)) {throw new Error(' duplicate className: ${eachClassName}`); } classMap.set(eachClassName, classes[eachClassName]); }); classMap.forEach((eachClass: any, keyName) => { instanceMap.set(keyName, new eachClass()); }); Instancemap. forEach((eachInstance: any, key: String) => {// Iterate over the injected class name eachInstance['_injectVariables_'] && eachInstance['_injectVariables_'].forEach((injectVariableKey: string) => { if (! instanceMap.get(eachInstance[injectVariableKey])) { throw new Error('injectName: ' + eachInstance[injectVariableKey] + ' not found! '); EachInstance [injectVariableKey] = instancemap. get(eachInstance[injectVariableKey]); }); delete eachInstance['_injectVariables_']; }); return instanceMap; };Copy the code
Store
export class DemoStore {
@observable data={}
}
Copy the code
Action
export class DemoAction {
@inject('DemoStore') store: DemoStore;
async getData() {
this.store.data = await fetch(...);
}
}
Copy the code
Component
interface Props { DemoStore? : DemoStore DemoAction? : DemoAction } @inject('DemoStore'.'DemoAction')
@observer
export class Demo extends Component<Props.any> {
render() {
const { data } = this.props.DemoStore;
return
<div onClick=(a)= >{this.props.DemoAction.getData()}>
{data}
</div>}}Copy the code
The new code
Provider
export const StoreContext = createContext(null);
export const ContextProvider = observer((props: any) = > {
const instances = injectInstance(
assign({}, props.inject)
);
const injects = {};
instances.forEach((value, key) = > {
injects[key] = value;
});
return (
<StoreContext.Provider value={injects}>
{props.children}
</StoreContext.Provider>
);
});
Copy the code
useInject
export const useInject = (name) = > {
const context = useContext(StoreContext);
if (name && context) {
return context[name];
}
return context;
};
Copy the code
Store
// Keep the same
Copy the code
Action
// Keep the same
@inject('DemoStore') store: DemoStore;
// If you can't get it, you can call it in init
// store: UCenterStore = useInject('DemoStore');
Copy the code
Component
import { useObserver } from 'mobx-react-lite';
export const Demo = memo((props: PropsDefine) = > {
const action: DemoAction = useInject('DemoAction');
const store: DemoStore = useInject('DemoStore');
useEffect(() = >{ action.getData(); } []);const handleClick = useCallback((item, index) = > {
// action.listItemClick(item, index);
// action.log({
// k: 'h5_click',
// v: 'hot_words'
// });} []);const { data } = store;
return useObserver(() = > (
<div className='creater-page'>.</div>))}Copy the code
conclusion
The new Provider still instantiates and assigns objects by Inject, while the action&Store writing method remains unchanged. Hook is used in Component, action and Store instances are obtained by usrInject, and UI response to store is realized by useObserver