davidmfoley / react-router-modal

Simple modals for react-router 4
MIT License
153 stars 20 forks source link

Doesn't work with router once modal link defined in entry point and modal placed in another component #5

Closed 01Kuzma closed 7 years ago

01Kuzma commented 7 years ago

Hi! I have a one-page website and a component called ‘Items’. In that component I’m using the react-router-modal. Items.js:

function ModalsName(props) {
  return (
    <div className="modal-dialog modal-lg">
    </div>  
  );
}

class Items extends React.Component {
  render() {
    return (
      <div className="container">
              <Link to="/modalsurl"> </Link>
        <ModalLink component={ModalsName} path={`/modalsurl`} />
         …other links
      </div>
    )
  }
}

module.exports = translate()(Items);

In such way everything works just fine. The modal is accessible by it’s own URL.

But if I try to add a router to the entry point of my app - index.js. The problems occurs. Firstly the called modal doesn’t open – I see only blank screen without any errors. Once I come back to previous page it hangs with a preloader. Only F5 re-renders the page. Index.js:

import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { ModalContainer } from 'react-router-modal'; 

class App extends React.Component {

  render() {
    return (
        <LandingPage />
    )
  }
}

ReactDOM.render(
  <I18nextProvider i18n={i18n}>
    <BrowserRouter>
      <div>
        <Route exact path="/" component={App} />
        <ModalLink path="/modalsurl" component={Items} />        
        <Route component={NoMatch} />
      </div>
    </BrowserRouter>
  </I18nextProvider>,
  document.getElementById('app')
);

It seems like a bug...

davidmfoley commented 7 years ago

Thanks for the report.

Looking at the snippets here, I'm not 100% sure what is going on.

Can you post a complete example source file that demonstrates the issue?

Thanks, Dave

01Kuzma commented 7 years ago

Hi! Spent an hour with webpackbin.com but haven't started the project in that sandbox. Could I send you a link to a dev app through PM?

davidmfoley commented 7 years ago

Sure; my email is in the package.json

01Kuzma commented 7 years ago

Thank you! Just PM'ed. A little information: with modal link routes defined the app goes to infinite loop

davidmfoley commented 7 years ago

@01Kuzma can you try v1.2.0 ? I fixed a similar problem that I encountered when rendering a modal inside another modal, and I think it may have also fixed the problem you are experiencing.

01Kuzma commented 7 years ago

Hi! @davidmfoley, it seems that the problem is fixed partly. The modal is rendered, but once I close it by clicking outside it the app for some reason hangs on my custom preloader. It seems that it trying to restart... Only F5 solves it. Could it be of my <ModalContainer /> or Route nesting or it's a bug?

I define Routes and <ModalContainer /> in such way:

  render() {
    return (      
      <I18nextProvider i18n={i18n}>
        <BrowserRouter>
            <div>
                <Route exact path="/" component={LandingPage} />
                <ModalRoute path="/someUrl" component={Items} />        
                <ModalRoute path="/someUrl2" component={Items} />   
                <ModalContainer />              
            </div>          
        </BrowserRouter>        
      </I18nextProvider>      
    )
  }
01Kuzma commented 7 years ago

Hi! It seems that there is a problem using the SWITCH from router. I’ve examined examples related to managing routes with not-found route component (404 page). Basically this construction is used:

<Switch>
  <Route exact path="/" component={Home}/>
  <Route path="/some_component" component={Some_component}/>
  <Route component={Notfound} />
</Switch>

By you suggestion I’ve moved ModalRoutes to separate file:

class PortfolioItems extends React.Component {

  render() {
    return (
      <div className="tems container">
        <ul>
          <div>
            <li>
              <Link to="/revel"></Link>
            </li>
            <li>
              <Link to="/marstena"></Link>
            </li>
          </div>
        </ul>
        <ModalRoute component={ExtendedRevel} path={`/revel`} parentPath='/' />
        <ModalRoute component={ExtendedMarstena} path={`/marstena`} parentPath='/' />
      </div>
    )
  }
}

And also additionally I’ve defined those routes inside the Switch of index.js:

  render() {
    return (
      <I18nextProvider i18n={i18n}>
        <div>
          <BrowserRouter>
            <Switch>
              <Route exact path="/" component={LandingPage} />
              <Route exact path={`/revel`} component={PortfolioItems}/>
              <Route exact path={`/marstena`} component={PortfolioItems}
              <Route component={NoMatch} />
            </Switch>
          </BrowserRouter>
          <ModalContainer />
        </div>
      </I18nextProvider>
    )
  }

As the result all routes are accessible and not found component also is triggered. But once the modal is opened the backdrop gray cover swaps the default background. And once the modal is closed the app is redirected to my custom preloader and hangs on, as it was previously.

davidmfoley commented 7 years ago

I don't think this is related to react-router-modal. For react-router-modal to show a modal on top of another component, both the modal route and the other component (in this case, the route selected by the <Switch /> must match the current location. In this case, it looks like the Switch is matching <PortfolioItems />, not <LandingPage />, which is (I think) what you want. I'm not sure what browser that is, but I have found that using the react developer tools plugin makes it a lot easier to debug these sorts of issues -- it lets you see the components that are rendered at any given moment. You might try installing it and see if it helps: https://github.com/facebook/react-devtools

01Kuzma commented 7 years ago

Thank you for the answer! Actually the <LandingPage /> is the wrapper-component (or bootstrapper) for all one-page sections/components which are rendered one-by one. The <PortfolioItems /> is one of the components which is placed inside the <LandingPage />. In the <PortfolioItems /> the ModalRoutes are defined. So, you presume that the problem is in route definition? I will check the dev tools, thank you!

P.S. I've just changed the components inside the SWITCHand it seems that everything now is working.

            <Switch>
              <Route exact path="/" component={LandingPage} />
              <Route path={`/revel`} component={LandingPage}/>
              <Route path={`/marstena`} component={LandingPage}
              <Route component={NoMatch} />
            </Switch>

Thank you!