使用 mapStateToProps 连接到 redux 存储的确认模式给出错误

Confirmation modal connecting to redux store using mapStateToProps gives an ERROR

我有一个模态组件。单击模式的关闭按钮时,我需要显示一个确认模式。它有是和没有选项。 此确认组件已连接到 Redux 存储。

一切正常,直到我使用 mapStateToProps 将确认组件连接到商店。在那之后只有我开始收到这个错误。

错误:无法在 "Connect(_class)" 的上下文或属性中找到 "store"。要么将根组件包装在 a 中,要么将 "store" 作为 prop 显式传递给 "Connect(_class)"。 在不变量 (bundle.js:21701)

我附上了下面的图片。

这是我的确认模式。

import React, { Component, PropTypes } from 'react';
import AriaModal from 'react-aria-modal';
import { confirm } from '../util/confirm';
import { confirmable } from 'react-confirm';

class Confirmation extends Component {
  constructor(props) {
    super(props);
    this.getApplicationNode = this.getApplicationNode.bind(this);
  }

  getApplicationNode = () => {
    return document.getElementById('application');
  }

  render() {
    console.log("rendering confirmation....");
    const {
     okLabbel = 'OK',
     cancelLabel = 'Cancel',
     title,
     confirmation,
     show,
     proceed,
     dismiss,
     cancel,
     enableEscape = true,
   } = this.props;

    const modal =
        <AriaModal
          titleText="demo one"
          onExit={this.deactivateModal}
          mounted={this.props.modalActive}
          initialFocus="#demo-one-deactivate"
          getApplicationNode={this.getApplicationNode}
          underlayStyle={{ paddingTop: '2em' }}
        >
          <div id="test-modal" className="background">
            <div className='model-title'>
              <h3 className='pe-title'>{title}</h3>
            </div>
            <div className="modal-body">
              {confirmation}
            </div>
            <footer className="modal-footer">
              <button className="btn btn-info" onClick={cancel}>{cancelLabel}</button>
              <button className='btn btn-danger' onClick={proceed}>{okLabbel}</button>
            </footer>
          </div>
        </AriaModal>;

    return (
      <div>
        {modal}
      </div>
    );
  }

}

Confirmation.propTypes = {
  okLabbel: PropTypes.string,
  cancelLabel: PropTypes.string,
  title: PropTypes.string,
  confirmation: PropTypes.string,
  show: PropTypes.bool,
  proceed: PropTypes.func,     // called when ok button is clicked.
  cancel: PropTypes.func,      // called when cancel button is clicked.
  dismiss: PropTypes.func,     // called when backdrop is clicked or escaped.
  enableEscape: PropTypes.bool,
}

export default confirmable(Confirmation);

这就是我将它连接到容器组件中的商店的方式。

import { connect } from 'react-redux';
import Confirmation from '../components/Confirmation';

const mapStateToProps = (state) => {
  console.log("Calling mapStateToProps here!" + state.confirmation.modalActive);
  return { modalActive: state.confirmation.modalActive };
}

export default connect(mapStateToProps)(Confirmation);

您可能会在控制台中看到将可见性设置为 true 的初始操作工作正常,并且该操作会像这样记录在控制台中。

{type: ON_CONFIRM, payload: true}

这个mapStateToProps有什么问题?

您可能会找到项目的代码 here

为什么我会收到这个错误。这里出了什么问题?感谢任何帮助。

问题出在react-confirm库中。它在它自己的组件树中呈现您的确认模型,而不是在您的应用程序的组件树中。如果你查看它的 source code,你可以看到它在内部使用 ReactDOM.render 来创建一个新的组件树。这就像你在同一个页面上有两个 React 应用程序。

mapStateToProps 的 react-redux 使用 React context 来访问 store。但是由于connected Confirmation组件在不同的组件树中呈现,connect HoC无法通过context访问redux store。

最简单的解决办法是找到另一个没有这个问题的库。但或者,您可以使用 HoC 将 context 手动注入到连接的确认中。

这是一个可用于将上下文注入组件的 HoC:

function withContext(WrappedComponent, context){

  class ContextProvider extends React.Component {
    getChildContext() {
      return context;
    }

    render() {
      return <WrappedComponent {...this.props} />
    }
  }

  ContextProvider.childContextTypes = {};
  Object.keys(context).forEach(key => {
    ContextProvider.childContextTypes[key] = React.PropTypes.any.isRequired; 
  });

  return ContextProvider;
}

假设您在组件调用页面中呈现连接的 Confirmation 组件。然后你可以像这样使用上面的 HoC 注入上下文。

class Page extends React.Component {

  //......

  static contextTypes = {
    store: React.PropTypes.object.isRequired
  }

  render(){

    const ConfirmationWithContext = withContext(ConnectedConfirmation, this.context);

    return (
      //.....
      <ConfirmationWithContext/> // with your props
      //.....
    );
  }

}