0

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.

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

7 Comments

Sorry i am using react router v4 and there is no need to have one Router component in the root component.
The router doesn't have to be the root, but my point remains that you should only have one router in your application.
I understand it. Can you please help me at this ? I have to use Router component in App.js ?
The <App> needs to be a child of your <Router> in order to have the router available through context.
Did so but still got undefined. I used Router in index.js where App is rendered. I then used contextTypes in app.js but still got undefined.
|
0

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

2 Comments

OP's question was about v4 which uses a different API than v2/3 and no longer has <Route> components nor does it rely on this.props.children for rendering.
its react router v4

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.