Search code examples
javascriptroutessingle-page-applicationurl-routingsolid-js

SolidJS Router doesn't render page - Navigation doesn't work


On navigation, even though the path of a Route is added to the url in the search bar, the component of the Route is not rendered. It only renders on refreshing the page.

My Header has buttons which are used for navigating to the different URLs (using useNavigate hook). When I click on each button, the path is added to the URL in the search bar but the previous component remains on the page and the new component is not shown.

Example, when I'm on '/,' 'Hi' is displayed but when I navigate to '/mybooks,' Books is not displayed and 'Hi' is still on the screen. I have to reload the page to get Books to display.

App.jsx :

function App() {
  return (
    <div class={styles.App}>
      <Header styles={styles} />
      <main>
        <Router>
          <Route path="/" component={() => <p>Hi!</p>} />
          <Route path="/mybooks" component={Books} />
          <Route path="/add" component={Add} />
        </Router>
      </main>
    </div>
  );
}

I have also wrapped App with a Router in index.jsx :

render(() => (
  <Router root={App} />
), root);

I have tried removing the inner Router thinking that was causing the problem, but when I do that, nothing is rendered (none of the three components supposed to be rendered are displayed) and I also get a warning (Unrecognized value. Skipped inserting.)

I want to know why the component is not being rendered without refreshing the page. How do I solve this and get each page to render as soon as I navigate to the path defined in the Route tag for each component?


Solution

  • You are not using the Router API as intended. The root is for providing a layout, not for the application root.The App component should return the Router:

    function App() {
      return (
        <Router root={Layout}>
          <Route path="/" component={Home} />
          <Route path="/about" component={About} />
        </Router>
      );
    }
    

    Here is a working demo:

    import { Route, RouteSectionProps, Router } from "@solidjs/router";
    import { Component } from "solid-js";
    import { render } from "solid-js/web";
    
    const Home = () => {
      return (
        <div>
          <h1>Home</h1>
        </div>
      )
    };
    const About = () => {
      return (
        <div>
          <h1>About</h1>
        </div>
      )
    };
    
    const Layout: Component<RouteSectionProps> = (props) => {
      return (
        <main>
          <nav>
            <a href="/">Home</a>
            <a href="/about">About</a>
          </nav>
          {props.children}
        </main>
      );
    }
    
    function App() {
      return (
        <Router root={Layout}>
          <Route path="/" component={Home} />
          <Route path="/about" component={About} />
        </Router>
      );
    }
    
    render(() => <App />, document.body);
    

    In the layout component you can use either the <a> element or the <A> component. The latter allows the use of relative path to its parent.