How to instantiate react component with injected properties

人走茶凉 提交于 2019-12-04 05:08:22

问题


I'm converting a react project from redux to mobx, and I'm having the following problem: I was using the container/presenter pattern with redux, which meant using the redux "connect" function, like this:

 export default connect(mapStateToProps, mapDispatchToProps)(Leads);

The problem I'm having is that there's no equivalent mobx function, so instead, I tried to simply create an instance of the component in the container. Something like:

render() {
  return (
    <MyComponent
      store={mystore}
    />
  );
}

Unfortunately, that doesn't work, because MyComponent has injected properties from react-router, something like this:

class MyComponent extends React.Component<ReportProps & RouteComponentProps<ReportProps>> {

  constructor(public routeProps: ReportProps & RouteComponentProps<ReportProps>) {
    super(routeProps);
  }...

I tried getting rid of the container concept, but the same problem occurs in other places because I'm using the mobx-react @inject decorator. For example, I have a component like this:

export interface AddressProps {
  report: IReportStore;
}

@inject((rootStore: RootStore) => ({
  report: rootStore.report
}))
@observer
class Address extends React.Component<AddressProps> {
...

If I then try to use my component somewhere, typescript complains that I'm not passing the required property (report, in this instance), even though I shouldn't need to, since I'm injecting the properties.

I figure I must be missing something basic, as this is a fairly straightforward use of mobx. Or maybe it's just a typescript problem...? If so, any ideas how to fix or work around it?

Thanks in advance, Jonathan


回答1:


There are a lot of problems around the mobx inject method.

the original idea was to return a Partial<TProps> but you can't do this typed without losing your original Class: React.Component<Partial<TProps>,TState> != YourComponent - the set properties.

Read the discussed problem here: https://github.com/mobxjs/mobx-react/issues/256

Simplistic solution

Use optional parameters in props and set them in a getter property:

interface AppProps {
    store?: SDtore;
}

class App {
  get store(): TimeEntryStore {
    return this.props.store as Store;
  }
  method(){
     this.store;///
  }
}

Other solution

If you want to keep your required parameters (eg: for using the component outside of mobx etc).

You can consider casting the component to React.Component<TPropsReduced,State> where TPropsReduced is a self defined interface with required props after injected.

The downsides are:

  • Losing type safety at casting (eg if you make mistakes/typo's in the interface properties. (can be solved by extending/subclassing interfaces.
  • Losing methods calls. You will no longer have typed methods on the component (eg: when you use ref={()=>}), but using this is dis-advised anyways.

Example:

interface AddressPropsMobx {
}

interface AddressProps extends AddressPropsMobx {
  report: IReportStore;
}



//Pure react component
class Address extends React.Component<AddressProps> {}

// Mobx version:
const MobxAddress = inject((rootStore: RootStore) => ({
  report: rootStore.report
}))(observer(Address)) as React.Component<AddressPropsMobx>;  //unsafe cast


来源:https://stackoverflow.com/questions/50318437/how-to-instantiate-react-component-with-injected-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!