React: Как обернуть компонент HOC? (доступ к свойству входа в систему через компоненты)

У меня есть приложение реакции (с redux и response-router), которое в разные моменты должно знать, вошел ли пользователь в систему, в зависимости от состояния некоторых данных в магазине и множества других вещей, связанных с данными в магазине. .

Для этого я создал компонент более высокого порядка, например:

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

export function masterComponent(Component){

  class MasterComponent extends React.Component {

    constructor(props){
      super(props);
    }

    loggedIn(){
      return this.props.player.token? true : false
    }

    render(){
      return (
        <Component {...this.props} player={{loggedIn: this.loggedIn()}}/>
      );
    }
  }

  UserComponent.propTypes = {
    player: React.PropTypes.object
  };


  function mapStateToProps(state) {
    return state;
  }

  return connect(
    mapStateToProps
  )(MasterComponent);

}

Мой вопрос в том, как лучше всего обернуть это вокруг моих отдельных компонентов? В настоящее время я реализовал это так, что каждый отдельный компонент обертывается при передаче для подключения, что работает нормально, но кажется немного неэффективным. то есть:

import {masterComponent} from '../HigherOrderComponents/MasterComponent';

export class ResultsPage extends React.Component {

  constructor(props){
.....
  }


  render(){
    return (
       .....
    );
  }
}



export default connect(
  mapStateToProps,
  mapDispatchToProps
)(masterComponent(ResultsPage));

Есть лучший способ сделать это?


person Fraser    schedule 21.02.2017    source источник


Ответы (1)


Это действительно зависит от вашего варианта использования, я вижу 3 возможных решения. Код ниже непроверенный и полу-псевдо.

Ваше первоначальное предложение после рефакторинга

export function masterComponent(Component) {

  const MasterComponent = (props) => {
    const loggedIn = props.player.token? true : false;

    // initial solution would override player, so you need 
    // something like this
    const player = { 
      ...this.props.player,
      loggedIn,
    };

    return <Component {...this.props} player={player} />
  }

  // Important! Here is the crucial part of the refactoring, 
  // not the coding style changes. Map only the relevant 
  // state properties, otherwise the component would rerender 
  // whenever any state property changed. 
  return connect(state => ({ player: this.state.player }))(MasterComponent);
}

Redux Middleware (мой личный выбор)

function loginMiddleware() {
  return store => next => action => {
    if (action.type === 'ADD_CREDENTIALS') {
      const { player } = store.getState();
      loginService.setPlayer(player);
    }

    // removePlayer if action.type === 'LOGOUT';

    return next(action);
  }
}

и в любом компоненте, который вы могли бы использовать

loginService.getPlayer() 

чтобы проверить, вошел ли кто-то в систему или нет

Недостаток по сравнению с вашим подходом: если действие 'ADD_CREDENTIALS' было отправлено, но компонент, который запрашивает loginService.getPlayer(), не подвергается повторной визуализации / обновлению, вы можете получить несогласованное состояние. Я уверен, что вы могли бы решить эту проблему, обладая более конкретными знаниями о вашем приложении.

Контекст (мой нелюбимый)

Используйте context React и передайте желаемое свойство всем другим компонентам.

person Lyubomir    schedule 21.02.2017