【问题标题】:cannot use router context [react-router v4]无法使用路由器上下文 [react-router v4]
【发布时间】:2017-04-09 22:40:34
【问题描述】:

我想在单击按钮时重定向到注册或登录路径,因为该按钮也负责显示模式。我在父组件中有一个 showModal 函数,即作为道具传递给子组件(Nav)的 App。由于我负责处理 onClick 事件的 showModal 函数位于 App 组件中,因此我尝试在那里使用路由器上下文,但我得到了 undefined

这是我的代码

index.js

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <ConnectedIntlProvider>
      <Router>
        <App />
      </Router>
    </ConnectedIntlProvider>
  </Provider>
  , document.querySelector('.app'));

class App extends Component {
  constructor(props, context) {
    super(props, context);
    console.log('context', context);
    this.state = { show: false };
  }

  showModal(e) {
    e.preventDefault();
    this.setState({ show: true });
    this.context.router.transitionTo(e.target.href);
  }

  hideModal() {
    this.setState({ show: false });
  }

  render() {
    return (
        <div className="container-fluid">
          <Nav
            showModal={(e) => this.showModal(e)}
            hideModal={() => this.hideModal()}
            show={this.state.show}
            onHide={() => this.hideModal()}
          />
        </div>
        );
  }
}

App.contextTypes = {
  router: React.PropTypes.object
};



const Nav = (props) => (
    <div>
      <nav className="navbar navbar-default">
        <div className="container-fluid">
          <div className="navbar-header">
            <a className="navbar-brand" href="">
              <img
                alt="Brand"
                className="img-responsive"
                src={logo}
                role="presentation"
              />
            </a>
          </div>
          <div className="collapse navbar-collapse" id="collapse-1">
            <ul className="nav navbar-nav navbar-right nav-social-icon">
              <li className="dropdown">
                <a
                  href=""
                  className="dropdown-toggle"
                  data-toggle="dropdown"
                >
                  ES
                  <span className="caret" />
                </a>
                <ul className="dropdown-menu" style={{ color: '#000', fontWeight: 'bold' }}>
                  <li onClick={() => props.selectedLocale('en')}>
                    en
                  </li>
                  <li onClick={() => props.selectedLocale('es')}>
                    es
                  </li>
                </ul>
              </li>
              <li className="btn-group regLog">
                <button
                  className="btn btn-default"
                  onClick={props.showModal}
                >
                  <Link to={{ pathname: '/signup' }}>
                    {props.intl.formatMessage({ id: 'nav.registration.text' }) }
                  </Link>
                </button>
                <button
                  onClick={props.showModal}
                  className="btn btn-default"
                >
                  <Link to={{ pathname: '/login' }}>
                    {props.intl.formatMessage({ id: 'nav.login.text' }) }
                  </Link>
                </button>
                {props.show ?
                  <ModalForm
                    show={props.show}
                    onHide={props.onHide}
                  /> : <span />
                }
              </li>
            </ul>
          </div>
        </div>
      </nav>
    </div>
  );


class ModalForm extends Component {
  render() {
    const { show, onHide, intl } = this.props;
    return (
        <Modal
          {...this.props}
          show={show}
          onHide={onHide}
          dialogClassName="custom-modal"
        >
          <Modal.Header closeButton>
            <Link to='/login' className="logTitle">
              <Modal.Title id="contained-modal-title-lg">
                {intl.formatMessage({ id: 'nav.login.text' })}
              </Modal.Title>
            </Link>
            <Link to='/signup' className="logTitle">
              <Modal.Title id="contained-modal-title-lg">
                {intl.formatMessage({ id: 'nav.registration.text' })}
              </Modal.Title>
            </Link>
          </Modal.Header>
          <Modal.Body>
            <Match pattern='/login' component={Login} />
            <Match pattern='/signup' component={Signup} />
          </Modal.Body>
        </Modal>
    );
  }
}

我正在使用 react-router v4

【问题讨论】:

    标签: javascript reactjs react-router


    【解决方案1】:

    您的代码有点奇怪,因为您使用了多个&lt;Router&gt; 组件。在组件树根附近的某个位置,您应该只有一个 &lt;___Router&gt;BrowserHashMemory)。

    ReactDOM.render((
      <BrowserRouter>
        <App />
      </BrowserRouter>
    ), document.getElementById('root'))
    

    router 上下文仅可用于&lt;Router&gt; 组件的子元素。您的&lt;Router&gt;&lt;App&gt; 组件的子组件,因此&lt;App&gt; 无权访问router 上下文变量。

    注意:我的回答是基于我可以看到的代码,其中不包括组件树的根。如果您在上面定义了另一个 &lt;Router&gt;,则应将其包含在您提供的代码中,以帮助更好地回答您的问题。

    【讨论】:

    • 对不起,我使用的是 react router v4,根组件中不需要有一个 Router 组件。
    • 路由器不必是根,但我的观点仍然是您的应用程序中应该只有一个路由器。
    • 我明白了。你能帮帮我吗?我必须在 App.js 中使用路由器组件?
    • &lt;App&gt; 必须是您的&lt;Router&gt; 的子级,才能使router 在上下文中可用。
    • 这样做了,但仍然未定义。我在渲染 App 的 index.js 中使用了路由器。然后我在 app.js 中使用了 contextTypes,但仍然没有定义。
    【解决方案2】:

    你需要做三件事

    首先你需要添加子路由

     <Route  path="users" component={User}>
         <Route path="login"    component={Login}/>
     </Route>
    

    然后,在你的父组件中添加这个,它会自动从 Url 中检测组件并根据它渲染组件。

    {this.props.children}
    

    现在您需要为登录模式创建单独的组件。并在这个模态打开模态框使用这个

    componentDidMount: function(){       
      $('#login-modal').modal('show');      
    },
    

    【讨论】:

    • OP 的问题是关于 v4,它使用与 v2/3 不同的 API,不再有 &lt;Route> 组件,也不依赖 this.props.children 进行渲染。
    • 它的反应路由器 v4
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-18
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 2017-09-13
    • 2018-03-04
    相关资源
    最近更新 更多