Home > Software design >  SolidJS Router: How to render different sidebar in a nested route?
SolidJS Router: How to render different sidebar in a nested route?

Time:12-26

I'm trying to create nested routes with common elements.

In my app as shown below, top level routes works fine, content changes and header remains in its place.

But every time when I want to create another one Routes/Router to keep sidebar also, I keep failing.

<Router>
  <div >
    <header>
      {/* 
      header menu, logo, etc 
      should be visible at any page
    */}
    </header>
    <div >
      <Routes>
        <Route path="/" component={Home} />
        <Route path="/profile" component={Profile} />
        {/* other routes */}
      </Routes>
    </div>
  </div>
</Router>

In the Profile component I would like to create one more Routes component and I were trying to:

<div >
  <div >which should stay on page if users is on any 'profile' page, like home /profile, /profile/settings, /profile/favorites etc</div>
  <Routes>
    <Route path="/profile/settings" component={Setting} />
    {/* other routes */}
  </Routes>
  
</div>

Following also does not work:

<Route path="/profile">
  <div>some static el (sidebar)</div>
  <Route path="/" component={Profile} />
  <Route path="/settings" component={Settings} />
</Route>

Creating a component Sidebar and including it in every Profile-related component works, but it is not what I am trying to do.

CodePudding user response:

If you want to show sidebar in some components, just include it directly in your component, you don't need to go through routes.

If you like to populate the content of the sidebar differently depending on the route, you can conditionally render the content of sidebar. In the example below we render user related data if there is user id. You can use props to pass data from parent component if data is already available in the parent component.

By the way, your header element stays outside the routes, that is why it is shared by all paths and works as you expected. But that is not how we share components between different routes.

import { render, Show } from "solid-js/web";
import { A, Route, Router, Routes, useParams, useSearchParams } from "@solidjs/router";

const Sidebar = () => {
  const params = useParams();
  const id = () => params.id

  return (
    // Show specific data if there is `id`
    <Show when={id()} fallback={<div>Regular Content</div>}>
      <div>Specific Content for {id()}</div>
    </Show>
  )
};

const Users = () => {
  return (
    <div>
      Users Page
      <Sidebar />
    </div>
  );
};

const User = () => {
  return (
    <div>
      User Page
      <Sidebar />
    </div>
  );
};

const Home = () => {
  return (<div>Home Page</div>);
};

const App = () => {
  return (
    <div>
      <header>
        <A href="/">Home</A>
        {` `}
        <A href="/users">Users</A>
        {` `}
        <A href="/users/john">John</A>
      </header>
      <main>
        <Routes>
          <Route path="/" component={Home} />
          <Route path="/users" component={Users} />
          <Route path="/users/:id" component={User} />
        </Routes>
      </main>
    </div>
  );
}
render(
  () => (
    <Router>
      <App />
    </Router>
  ),
  document.body
);

Here is how you pass parameters from a route component to the sidebar component:

import { A, Route, Router, Routes, useParams } from "@solidjs/router";
import { Component } from "solid-js";
import { render, Show } from "solid-js/web";

const Sidebar: Component<{ greeting: string }> = (props) => {
  const params = useParams();
  const id = () => params.id

  return (
    <Show when={id()} fallback={<div>Content for the rest</div>}>
      <div>Content for {id()}</div>
      <div>{props.greeting}</div>
    </Show>
  )
};

const Users = () => {
  return (
    <div>
      Users
      <Sidebar greeting="Hello From Users" />
    </div>
  );
};

const User = () => {
  return (
    <div>
      User Page
      <Sidebar greeting="Greetings from User" />
    </div>
  );
};

const Home = () => {
  return (<div>Home Page</div>);
};

const App = () => {
  return (
    <div>
      <header>
        <A href="/">Home</A>
        {` `}
        <A href="/users">Users</A>
        {` `}
        <A href="/users/john">John</A>
      </header>
      <main>
        <Routes>
          <Route path="/" component={Home} />
          <Route path="/users" component={Users} />
          <Route path="/users/:id" component={User} />
        </Routes>
      </main>
    </div>
  );
}
  • Related