Как написать компонент высокого порядка ReactJS, используя ES6? - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь создать компонент высокого порядка ReactJS с использованием синтаксиса ES6. Вот моя попытка:

export const withContext = Component =>
    class AppContextComponent extends React.Component {
        render() {
            return (
                <AppContextLoader>
                     <AppContext.Consumer>
                        {context => <Component {...props} context={context} />}
                    </AppContext.Consumer>
               </AppContextLoader>
            );
        }
    };

Здесь AppContextLoader получает контекст из базы данных и предоставляет его контексту:

class AppContextLoader extends Component {
  state = {
    user: null,
  };

  componentWillMount = () => {
    let user = databaseProvider.getUserInfo();
    this.setState({
      user: user
      });
  };


  render = () => {
    return (
      <AppContext.Provider value={this.state}>
        {this.props.children}
      </AppContext.Provider>
    );
  };
}

export default AppContextLoader;

И использование:

class App extends Component {
    static propTypes = {
         title: PropTypes.string,
         module: PropTypes.string
    }

    render = () => {
        return (
                withContext(
                <Dashboard
                    module={this.props.module}
                    title={this.props.title}
                />
                );

export default App;

По какой-то причине мой обернутый компонент (Dashboard) не получает моего свойства context, только исходные (title и module).

Как правильно написать HOC, используя синтаксис ES6?

Ответы [ 3 ]

0 голосов
/ 27 апреля 2018

Это должно быть this.props вместо:

<Component {...this.props}

Это должно работать для вас:

render() {
  const props = this.props;
  return (
    <AppContext.Consumer>
      {context => <Component {...props} context={context} />}
    </AppContext.Consumer>
  );
}
0 голосов
/ 01 августа 2018

У вас есть несколько проблем:

  1. Вы не используете API контекста должным образом - контекст создан для использования Provider для предоставления значения одному или нескольким Consumers - вы создаете с помощью нового Provider и Consumer.

  2. из вашего примера вам не нужно использовать Context - используйте hoc для новых данных использования - withUserData

  3. Вы должны использовать this.props, а не реквизит

  4. В разделе использования вы передаете hoc элемент, а не компонент

  5. Вы не получаете реквизит от withContext

Решение

export const withUserData = BaseComponent =>
  class AppContextLoader extends Component {
    state = {
      user: null,
    };

    componentWillMount = () => {
      let user = databaseProvider.getUserInfo();
      this.setState({
        user: user
      });
    };


    render = () => {
      return (
        <BaseComponent {...this.props} {...this.state} />
      );
    };
  }

И использование:

class App extends Component {
    static propTypes = {
         title: PropTypes.string,
         module: PropTypes.string
    }

    render = () => {
        return (
                  <EnhancedDashboard
                    module={this.props.module}
                    title={this.props.title}
                  />
                );
     }


const EnhancedDashboard = withUserData(Dashboard)

export default App;
0 голосов
/ 27 апреля 2018

Вы неправильно используете HOC, вам нужно передать компонент, а не экземпляр компонента. Также вызов HOC из-за рендера является плохим патентом, так как при каждом рендеринге будет возвращаться новый компонент, вы должны написать

const DashboardWithContext = withContext(Dashboard);
class App extends Component {
    render = () => {
        return (
                <DashboardWithContext
                    module={"ADMIN"}
                    title={"MY APP"}
                />
        )
    }
}

export default App;

Также в withContext HOC, поскольку возвращаемый компонент является классом, вы получите доступ к реквизитам, таким как {...this.props} вместо {...props}. Однако имеет смысл использовать функциональный компонент, поскольку на самом деле вы не используете методы жизненного цикла

 export const withContext = Component => (props) => (
            <AppContext.Consumer>
                {context => <Component {...props} context={context} />}
            </AppContext.Consumer>
        );

Рабочие коды и коробка

...