Как создать экземпляр React компонента с введенными свойствами

Я конвертирую проект реакции из redux в mobx, и у меня возникла следующая проблема: я использовал шаблон контейнер / презентатор с redux, что означало использование функции «connect» redux, например:

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

Проблема, с которой я столкнулся, заключается в том, что нет эквивалентной функции mobx, поэтому вместо этого я попытался просто создать экземпляр компонента в контейнере. Что-то вроде:

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

К сожалению, это не работает, потому что MyComponent внедрил свойства из response-router, примерно так:

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

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

Я попытался избавиться от концепции контейнера, но та же проблема возникает и в других местах, потому что я использую декоратор mobx-react @inject. Например, у меня есть такой компонент:

export interface AddressProps {
  report: IReportStore;
}

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

Если затем я попытаюсь использовать где-нибудь свой компонент, машинописный текст будет жаловаться, что я не передаю требуемое свойство (в данном случае - report), хотя мне и не нужно, поскольку я ввожу свойства.

Я полагаю, что мне не хватает чего-то базового, так как это довольно простое использование mobx. А может это просто проблема машинописного текста ...? Если да, есть идеи, как это исправить или обойти?

Заранее спасибо, Джонатан


person jonneve    schedule 13.05.2018    source источник


Ответы (1)


Есть много проблем с методом инъекции mobx.

первоначальная идея заключалась в том, чтобы вернуть Partial<TProps>, но вы не можете сделать это напечатанным без потери исходного Class: React.Component<Partial<TProps>,TState>! = YourComponent - установленные свойства.

Прочтите обсуждаемую проблему здесь: https://github.com/mobxjs/mobx-react/issues/256

Упрощенное решение

Используйте необязательные параметры в props и установите их в свойстве getter:

interface AppProps {
    store?: SDtore;
}

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

Другое решение

Если вы хотите сохранить необходимые параметры (например: для использования компонента вне mobx и т. Д.).

Вы можете рассмотреть приведение компонента к React.Component<TPropsReduced,State>, где TPropsReduced - это самоопределяемый интерфейс с необходимыми реквизитами после внедрения.

Минусы:

  • Потеря безопасности типов при приведении типов (например, если вы делаете ошибки / опечатки в свойствах интерфейса. (Может быть решена путем расширения / создания подклассов интерфейсов.
  • Потеря вызовов методов. У вас больше не будет типизированных методов в компоненте (например, когда вы используете ref={()=>}), но в любом случае использовать это не рекомендуется.

Пример:

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
person Joel Harkes    schedule 14.05.2018
comment
Спасибо за ответ! Я решил свою проблему, используя одно из многих решений, предложенных на странице проблемы github, на которую вы ссылались: Теперь у меня есть служебная функция с именем typedInject, которую я оборачиваю вокруг своего компонента перед его экспортом, и она отлично работает. Просто сделать свойства необязательными - слишком сложно, потому что вам нужно будет проверять, определено ли оно каждый раз, когда вы пытаетесь его использовать ... - person jonneve; 14.05.2018