简体   繁体   中英

React router dom and layouts

I want to use layouts with my react-router-dom, at this moment i am doing that like this

const DefaultLayout = ({children, ...rest}) => {
    return (
        <div className={styles.wrapper}>
            <Header/>
            {children}
            <Footer/>
        </div>
    )
};

const DefaultRoute = ({component: Component, ...rest}) => {
    return (
        <Route {...rest} render={matchProps => (
            <DefaultLayout>
                <Component {...matchProps} />
            </DefaultLayout>
        )}/>
    )
};

render(
    <Provider store={store}>
        <HashRouter>
            <Switch>
                <DefaultRoute exact path="/" component={AdvertList}/>
                <DefaultRoute exact path="/user" component={UserOptions}/>
                <Route path="/login" children={Login}/>

                <Route render={
                    () => (
                        <div>
                            Not found
                        </div>
                    )
                }/>
            </Switch>
        </HashRouter>
    </Provider>,
    document.querySelector('#app')
);

it works okay, both UserOptions and AdvertList components are rendered inside DefaultLayout , and Login component does not, but in official documentation i didn't find solution like that, instead there is " nested routing " where you adding new nested routes in subclasses, like

if you need default layout u make it on route / , then if you need advert list with that layout, in layout component you defined route /adverts and adding link to it, and so on, each sub component uses layout of parent one.

But in my case there is already product list on route / , and i need to change that content to other products list regarding link pressed, not to add to parent layout, but to change it part. Here is my code,

const { BrowserRouter, Route, Switch, Link } = window.ReactRouterDOM;
const { Component } = window.React;


const About = () => ('About');
const MiscProducts = () => ('Misc products');

class AdvertsList extends Component {
    render() {
        return (
          <div className="container">
            <header>Header</header>
            <main>
              <nav>
                <Link to="/miscProducts">Misc Products</Link> #
                <Link to="/about">About</Link>
              </nav>
               <div className="content">
                 Main Products
               </div>
            </main>
            <footer>Footer</footer>

            <Route path="/miscProducts" component={MiscProducts} />
          </div>
        )
    };
};

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <Switch>
            <Route path="/" component={AdvertsList} />
            <Route path="/about" component={About} />

            <Route path="*" render={
                () => (
                  <div>
                    Not found
                  </div>
                )
              }/>
        </Switch>
      </BrowserRouter>
    );
  }
}

ReactDOM.render(<App />, document.querySelector("#app"));

http://jsfiddle.net/gmcke2a4/6/ here main products loaded by default, and when i press misc products, misc products must be loaded instead of main one.

ps And why about doesn't work?

Login Fix

<Route path="/login" children={Login}/> this seems wrong because children component expects function which return nodes i think.Try <Route path="/login" children={() => (</Login />)}

Layout

But in my case there is already product list on route /, and i need to change that content to other products list regarding link pressed, not to add to parent layout

You can create component which renders specific products like this.

const MainProducts = () => 'Main Products'
const GummyBearsProducts = () => 'GummyBears'

const Products = props => (

 <div className="products-container">
   <Switch>
   <Route path={`${props.location.pathname}`} component={MainProducts}/> 
   <Route path={`${props.location.pathname}/gummy-bears`} components={GummyBearProducts}/> 
   </Switch>
</div>

)

And then use it as follows.

class AdvertsList extends Component {
    render() {
        return (
          <div className="container">
            <header>Header</header>
            <main>
              <nav>
                <Link to="/products">Products</Link> #
                <Link to="/about">About</Link>
              </nav>
               <div className="content">
                 <Route path="/products" component={Products} />
               </div>
            </main>
            <footer>Footer</footer>


          </div>
        )
    };
};

React router is great in rendering specific components.I hope it answers your question.Cheers!

If you are using react-router-dom v6. Then follow the below procedure to configure react-router-dom,

App.jsx:

import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './Components/Home'
import About from './Components/About'
import Layout from './Components/Layout'


function App() {
  return (
    <div className="App">

      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Layout />}>
            <Route path="/" element={<Home />} />
            <Route path="about" element={<About />} />
          </Route>
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;

After configuring the react router in App.jsx. I am creating 3 components Home, About and Layout. Home and About are regular components and Layout component is to handle the Layout part in react-router-dom using Outlet .

Layout.jsx

import { Outlet, Link } from 'react-router-dom'
export default function Layout() {
    return (
        <>

            <Link to="/">Home</Link>&nbsp;&nbsp;&nbsp;
            <Link to="/about">About</Link>
            <Outlet />
        </>
    )
}

Home.jsx

export default function Home() {
    return (
        <>
            <p>This is Home</p>
        </>
    )
}

About.jsx

export default function About() {
    return (
        <>
            <p>This is About Us</p>
        </>
    )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM