Serenity
Serenity

Reputation: 4054

cannot use router context [react-router v4]

i want to redirect to either register or login route when button is clicked as the button is responsible to show modal too. I have a showModal function in parent component i.e App that is passed to child component(Nav) as a prop. As my showModal function which is responsible for handling onClick event is in App component, i tried to use router context there but i am getting undefined .

Here is my code

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

I am using react-router v4.

Upvotes: 0

Views: 1422

Answers (2)

Anuj Dhanju
Anuj Dhanju

Reputation: 523

You need to do three thing

First you need to add child route like

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

After that, add this in your parent component, this will detect component automatically from Url and render component according to that.

{this.props.children}

Now you need to create separate component for login modal. And in this modal open modal box using this

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

Upvotes: 0

Paul S
Paul S

Reputation: 36787

Your code is a bit strange because you are using multiple <Router> components. You should only have one <___Router> (either Browser, Hash or Memory) somewhere near the root of your component tree.

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

The router context is only available to child elements of a <Router> component. Your <Router> is a child of the <App> component, so the <App> does not have access to the router context variable.

Note: My answer is based off of the code that I can see, which does not include the root of your component tree. If you have another <Router> defined higher up, that should be included in the code which you provide to help to better answer your question.

Upvotes: 1

Related Questions