reactjs - React : How to wrap component with HOC?(跨组件访问登录属性)

标签 reactjs redux react-router higher-order-functions higher-order-components

我有一个react(带有redux和react-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));

有更好的方法吗?

最佳答案

这实际上取决于您的用例,我看到 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 中间件(我个人的选择)

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' 已分派(dispatch),但请求 loginService.getPlayer() 的组件没有分派(dispatch)如果不重新渲染/更新,您可能会得到不一致的状态。我相信您可以通过更具体的应用程序知识来解决这个问题。

上下文(我最不喜欢的)

使用 React context并将所需的属性传递给所有其他组件。

关于reactjs - React : How to wrap component with HOC?(跨组件访问登录属性),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42372614/

相关文章:

javascript - React-Redux——从列表中选择项目

javascript - 如何划分 Redux reducer 和 action creator 之间的逻辑?

javascript - Redux mapStateToProps 属性依赖

javascript - React Router 不编码 & 符号,而是对路径参数中的空格进行编码

javascript - 使用 React 一次突出显示一个对象

reactjs - RBuilder和RDomBuilder有什么区别?

javascript - 如何为 React Chart JS 中的点创建 OnClick 事件?

reactjs - 使用 ReactJS、Redux 和 Websocket 进行实时更新

javascript - 以编程方式重定向到 react 路由器 v6 中的路由的问题

reactjs - React redux-beacon 跟踪链接点击分析