反应:如何用HOC包装组件? (跨组件访问登录属性) [英] React: How to wrap component with HOC? (access login property across components)

查看:97
本文介绍了反应:如何用HOC包装组件? (跨组件访问登录属性)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个react(使用redux和amp; react-router)应用程序,该应用程序需要根据存储中某些数据的状态以及与之相关的其他信息,在各个点上了解用户是否已登录存储中的数据.

I have a react (with redux & react-router) app that at various points needs to know whether or not a user is logged in based on the state of some data in the store and a bunch of other things tied to data in the store.

为此,我创建了一个像这样的高阶组件:

To achieve this, I've created a higher order component like so:

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);

}

我的问题是,如何最好地将其包装在我的各个组件周围?目前,我已经实现了它,以便每个单独的组件在传递给连接时都被包裹起来,虽然可以正常工作,但是感觉效率低下.即:

My question is how is best to wrap this around my individual components? Currently I have implemented it so that each individual component is wrapped when passed to connect which works fine but feels a little inefficient. ie:

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

export class ResultsPage extends React.Component {

  constructor(props){
.....
  }


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



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

有更好的方法吗?

推荐答案

这确实取决于您的用例,我看到3种可能的解决方案.下面的代码未经测试且是半伪的.

It really depends on your use case, I see 3 possible solutions. Code below is untested and semi-pseudo.

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);
  }
}

以及您可以使用的任何组件

and in any component you could use

loginService.getPlayer() 

验证是否有人登录

缺点:如果已分派操作'ADD_CREDENTIALS',但没有重新呈现/更新请求loginService.getPlayer()的组件,则结果可能会不一致.我相信您可以通过对应用程序的更具体的了解来解决这个问题.

Disadvantage compared to your approach: If action 'ADD_CREDENTIALS' has been dispatched, but the component that requests loginService.getPlayer() doesn't get rerendered / updated, you might end up with inconsistent state. I'm sure you could solve that with more specific knowledge of your application.

使用React 上下文并将所需的属性传递给所有其他组件.

Use React context and pass the desired property to all other components.

这篇关于反应:如何用HOC包装组件? (跨组件访问登录属性)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆