react-redux如何从非儿童的其他容器全局访问数据

时间:2018-01-29 21:08:41

标签: reactjs redux react-redux

我不知道如何做到这一点,我理解如何在组件中存储数据,但在创建containers等时,它会因为需要渲染而变得混乱,但我只是想存储数据。在线官方文档不是很清楚。

我想将数据全局存储在setstate中,以便我可以从任何组件访问它。这将与所有用户信息相关。所以我可以导入用户状态,然后说user.isGuest等等。

我目前在头文件中执行以下操作,但是我需要将用户数据公开给任何组件,而不进行回调并将数据传递回App

import React, { Component } from 'react';
import {getHttpRequestJSON} from '../components/HTTP.js'
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { fetchActiveUser } from '../actions/index';
import { bindActionCreators } from 'redux';   

class Header extends Component {

    constructor(props){
        super(props);
        this.state = {
            loading: true,
            version: ''
        };
    }

    initData = () => {
        let self = this;

        getHttpRequestJSON('/api/user/get/user/method/is/guest/format/json?quiet=1')
        .then((response) => {
            let isGuest = response.body.recordset.record.isGuest;
            if(isGuest){
                /*$(".logo").trigger('click');
                //$("#overlay").show();
                $('#modalIntro').modal('toggle');

                $("#modalIntro").on("hidden.bs.modal", function () {
                    $(".logo").trigger('click');
                });*/
            }

            self.props.activeUser.isGuest = isGuest;
            self.setState({
                 loading : false,
                 version : response.header.version
            });
        })
        .catch(error => { 
            console.log("Failed!", error);
            //$('#myModalError .modal-body').html(error);
            //$('#myModalError').modal('show');
        }); 
    }

    componentDidMount() {
        this.props.fetchActiveUser();       
        this.initData();
     }

    render() {
        if(this.state.loading){
            return (
                    <div className="container-fluid" id="top_section">
                        <div id="flash_alert" className="row" style={{margin:"0 auto"}} >
                            <div className="alert alert-success col-xs-3 col-sm-6 col-lg-3 text-center">
                              <strong>Success!</strong>
                            </div>

                            <div className="alert alert-info col-xs-3 col-sm-6 col-lg-3 text-center">
                              <strong>Info!</strong>
                            </div>

                            <div className="alert alert-warning col-xs-3 col-sm-6 col-lg-3 text-center">
                              <strong>Warning!</strong>
                            </div>

                            <div className="alert alert-danger col-xs-3 col-sm-6 col-lg-3 text-center">
                              <strong>Danger!</strong>
                            </div>
                        </div>
                        <div className="logo">

                        </div>
                        <div className="row-fluid">
                            <div className="header">
                                <div className="row-fluid">
                                    <div className="col-xs-5 col-sm-7 col-md-9">
                                    <h2 style={{paddingLeft: "15px !important"}} className="ellipsis">Home</h2>
                                    </div>
                                    <div className="col-xs-4 col-sm-3 col-md-2 vcenter hidden-print" style={{textAlign: "right",fontSize: "8pt",bottom: "-28px",position: "relative",float: "right"}}>
                                        <span className="username"></span> | <Link className="logout" to={`/logout`}> Logout <img src="/images/page-layout/logout-button.gif" alt="Icon: Logout" title="Logout" /> </Link>
                                    </div>
                                </div>
                            </div>
                            <div className="row-fluid" style={{clear: "both",position: "relative",top: "-50px",marginLeft: "95px"}}>
                                <div className="col-sm-8"> </div>
                                <div className="col-sm-4 text-right">
                                    <Link to={`/home`}> Connectivity Compliance Portal (CCP) <span style={{fontSize:"7pt"}}></span> </Link>
                                </div>
                            </div>
                        </div>

                        <div id="myModalError" class="modal fade" role="dialog">
                            <div class="modal-dialog">

                              <div class="modal-content">
                                <div class="modal-header alert alert-danger">
                                  <button type="button" class="close" data-dismiss="modal">x</button>
                                  <h4 class="modal-title">Error</h4>
                                </div>
                                <div class="modal-body">
                                  Unexpected error occured
                                </div>
                                <div class="modal-footer">
                                    <button type="button" class="btn btn-success" data-dismiss="modal">Ok</button>
                                </div>
                              </div>

                            </div>
                          </div>
                    </div>
                        );
        }
        return (
                <div className="container-fluid" id="top_section">
                    <div id="flash_alert" className="row" style={{margin:"0 auto"}} >
                        <div className="alert alert-success col-xs-3 col-sm-6 col-lg-3 text-center">
                          <strong>Success!</strong>
                        </div>

                        <div className="alert alert-info col-xs-3 col-sm-6 col-lg-3 text-center">
                          <strong>Info!</strong>
                        </div>

                        <div className="alert alert-warning col-xs-3 col-sm-6 col-lg-3 text-center">
                          <strong>Warning!</strong>
                        </div>

                        <div className="alert alert-danger col-xs-3 col-sm-6 col-lg-3 text-center">
                          <strong>Danger!</strong>
                        </div>
                    </div>
                    <div className="logo">

                    </div>
                    <div className="row-fluid">
                        <div className="header">
                            <div className="row-fluid">
                                <div className="col-xs-5 col-sm-7 col-md-9">
                                <h2 style={{paddingLeft: "15px !important"}} className="ellipsis">Home</h2>
                                </div>
                                <div className="col-xs-4 col-sm-3 col-md-2 vcenter hidden-print" style={{textAlign: "right",fontSize: "8pt",bottom: "-28px",position: "relative",float: "right"}}>

                                            <span className="username">{this.props.activeUser.name}{` `}</span> | <Link className="logout" to={`/logout`}> Logout <img src="/images/page-layout/logout-button.gif" alt="Icon: Logout" title="Logout" /> </Link>
                                </div>
                            </div>
                        </div>
                        <div className="row-fluid" style={{clear: "both",position: "relative",top: "-50px",marginLeft: "95px"}}>
                            <div className="col-sm-8">
                                                </div>
                            <div className="col-sm-4 text-right">
                                <Link to={`/home`}>Connectivity Compliance Portal (CCP)<span style={{fontSize:"7pt"}}>{` `}v{` `}{this.state.version}</span></Link>
                            </div>
                        </div>
                    </div>

                    <div id="myModalError" class="modal fade" role="dialog">
                        <div class="modal-dialog">

                          <div class="modal-content">
                            <div class="modal-header alert alert-danger">
                              <button type="button" class="close" data-dismiss="modal">x</button>
                              <h4 class="modal-title">Error</h4>
                            </div>
                            <div class="modal-body">
                              Unexpected error occured
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-success" data-dismiss="modal">Ok</button>
                            </div>
                          </div>

                        </div>
                      </div>
                </div>

        );

    }
}

function mapStateToProps(state) {
    // Whatever is returned will show up as props
    // inside of the component
    return {
        activeUser: state.activeUser
    };
}

// Anything returned from this function will end up as props
// on this container
function mapDispatchToProps(dispatch){
    // Whenever getUser is called, the result should be passed
    // to all our reducers
    return bindActionCreators({ fetchActiveUser }, dispatch);
}

//Promote component to a container - it needs to know
//about this new dispatch method, fetchActiveUser. Make it available
//as a prop
export default connect(mapStateToProps, mapDispatchToProps)(Header);

我有另一个容器,我想访问fetchActiveUser的数据。

import _ from 'lodash';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchContents } from '../actions';
import { Link } from 'react-router-dom';
import { fetchActiveUser } from '../actions/index';
import { bindActionCreators } from 'redux';   

class HomeContent extends Component {

    componentDidMount() {
        this.props.fetchContents();
    }

    htmlDecode(input){
        let e = document.createElement('div');
        e.innerHTML = input;
        return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
    }

    renderContent(classname) {
        return _.map(this.props.content, c => {

            if(c.target == classname){
                return (                        
                    <div dangerouslySetInnerHTML={{ __html: c.content}} />
                );
            }
        });
    }

    render() {
console.log(this.props);
        return (
                <div className="container-fluid">

        <div className="row-fluid text-center" >
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">INTRODUCTION</h3>
                </div>
                <div className="panel-body panel_introduction">{this.renderContent('panel_introduction')}</div>
            </div>
        </div>


        <div className="row-fluid text-center top-buffer">
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">Whats New!</h3>
                </div>
                <div className="panel-body panel_whats_new">{this.renderContent('panel_whats_new')}</div>
            </div>
        </div>

        <div className="row-fluid text-center top-buffer">
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">DISCLAIMER</h3>
                </div>
                <div className="panel-body panel_disclaimer">{this.renderContent('panel_disclaimer')}</div>
            </div>
        </div>

        <div className="modal fade bs-example-modal-lg" id="modalIntro" tabIndex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
          <div className="modal-dialog modal-lg" role="document">
            <div className="modal-content">
              <div className="modal-header">
                <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 className="modal-title" id="myModalLabel">Welcome to the Connectivity Compliance Portal (CCP)</h4>
              </div>
              <div className="modal-body">
                You are receiving this message as you are a guest and require elevated privileges to make best use of the service. In order to do this you'll need to:
                    <ol start="1">
                      <li>Go to <a target="_blank" href="https://iam.domain.com/identity" target="_blank" >WIAM (https://iam.domain.com/identity)</a></li>
                      <li>Click on <i>"Request Access"</i> at the top</li>
                      <li>Search for <i>"CCP"</i></li>
                      <li>Select the relevant group and add it to the cart</li>
                      <li>Check Out!</li>
                    </ol>

                <p>You can confirm if you have been added to the group by going to <Link to={`/ldapuser`}>https://ccp.domain.com/ldapuser</Link>. Once you see you have been added to the group log out of CCP and log back in and you should have the correct permissions. The process can take a few hours to a couple of days depending on how long the approvers take.</p>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
              </div>
            </div>
          </div>
        </div>

    </div>
          );
    }
}

function mapStateToProps(state) {
    return { content: state.content }
}

//Anything returned from this function will end up as props
//on this container
function mapDispatchToProps(dispatch){
 // Whenever getUser is called, the result should be passed
 // to all our reducers
 return bindActionCreators({ fetchContents, fetchActiveUser }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(HomeContent);

1 个答案:

答案 0 :(得分:0)

React组件状态和redux状态是两回事。 redux中的状态是一个全局状态实例,您使用connect hoc将此状态的一部分连接到React组件。

因此,如果您想在两个组件之间共享用户状态,那么您只需connect这两个具有相同redux状态选择器的组件。 redux状态选择器的结果将作为props传递给您的react组件。 (因此名称mapStateToProps通常用于将redux状态映射到组件props)。

获取后,您可以使用react-redux的dispatch函数触发操作。

dispatch({
    type: 'DATA_RECEIVED',
    payload: {
       source:<your source>,
       data: <the data>,
    }      
 })

然后创建一个reducer并将其添加到root reducer:

export default (state ={}, action) => {
  switch(action.type){
     case 'DATA_RECEIVED': 
        return {
           ...state,
           [action.payload.source]: {
              ...state[action.payload.source],
              ...data
           }
        }
     default: return state;
  }
}

然后选择组件中的状态:

connect((state,props)=> state.yourReducerLocation[props.resource])(YourComponent)

这会将道具arg用于connect,因此您可以在resource上指定YourComponent

有几件事:

  1. 您应该使用const值和actionCreators(发出操作的函数)创建您的操作
  2. 您应该考虑减速器如何存储检索到的状态
  3. 用于选择数据,您应使用mapStateToProps函数
  4. 使用dispatch仅使用状态选择器时会自动添加
  5. connect,但最好添加dispatchToProps对象方法以使用{{自动包装actionCreators 1}}功能
  6. 对于高效选择器,您应该使用重新选择
  7. 对于副作用(即加载异步数据),请使用副作用中间件,例如&#39; redux-saga&#39;。