Можно ли передавать HOC через контекст React? - PullRequest
0 голосов
/ 23 мая 2019

У меня есть задача создать новый компонент React в существующем проекте. Проект состоит из нескольких подпроектов. Два из них:

  • WebApp: содержит большую часть логики приложения, хранилища Redux и «умных» компонентов React, подключенных к хранилищу Redux.
  • Design: содержит «немые» компоненты React, которые имеют стилизацию и могут иметь собственное локальное состояние.

Одно из правил проекта гласит, что компоненты Design можно импортировать в WebApp, но не наоборот. Таким образом, в случае, если «тупому» компоненту нужно запустить действие хранилища, один из «умных» компонентов должен раскрыть действие с помощью mapDispatchToProps и передать его до «тупого» компонента.

Проблема с моим новым компонентом заключается в том, что он может использоваться во многих местах проекта, иногда довольно глубоко в цепочке «тупых» компонентов. Таким образом, в случае, если я буду следовать правилам проекта, мне придется обновить множество «тупых» компонентов всеми новыми свойствами, которые должен получить мой компонент.

Чтобы избежать этого, я попытался использовать HOC-подобный «умный» компонент и передать его через контекст React моему «тупому» компоненту. Я говорю «HOC-like», потому что это не классический HOC, а тот, который использует свойство render .

Мой «умный» компонент из WebApp:

import React, { Component } from 'react';
import { connect } from 'react-redux';

class MySmartComponent extends Component {
  render() {
    return (
      <>
        {this.props.render({
          someAction: this.props.someAction,
        })}
      </>
    );
  }
}

const mapDispatchToProps = dispatch => ({
  someAction: payload => {
    /* something happens*/
  },
});

export default connect(mapDispatchToProps)(MySmartComponent);

Мой "тупой" компонент из Design:

import React, { Component } from 'react';

export const MyContext = React.createContext({});

class MyDumbComponent extends Component {
  render() {
    return (
      <MyContext.Consumer>
        {({ MySmartComponent }) => {
          return (
            <MySmartComponent
              render={({ someAction }) => (
                <>/* someAction can be used here */</>
              )}
            />
          );
        }}
      </MyContext.Consumer>
    );
  }
}

export default MyDumbComponent;

И затем я предоставляю MySmartComponent в качестве контекста в некоторых корневых компонентах в WebApp:

import React, { Component } from 'react';
import { MyContext } from 'Design/MyDumbComponent';
import MySmartComponent from 'WebApp/MySmartComponent';

const myContext = { MySmartComponent };

class SomeRootComponent extends Component {
  render() {
    return (
      /* ... */
      <MyContext.Provider value={myContext}>
        {this.props.children}
      </MyContext.Provider>
      /* ... */
    );
  }
}

export default SomeRootComponent;

Я подозреваю, что это может быть неправильным использованием контекста React. Или, может быть, это просто плохая практика? Но тогда, что может быть минусами?

...