Home > OS >  The <Link></Link> react-tag seems to be preventing my app from rendering
The <Link></Link> react-tag seems to be preventing my app from rendering

Time:02-25

I am trying to construct/replicate an e-commerce website using React. When trying to launch the dev server, I noticed that I wasn't getting anything rendered on my screen. Using the React Dev tools extension confirmed as much. From past experiences, adding the links to the App.js file would probably solve this, however, I'd rather have the links in the Header component. I am trying to link the image such that when I click on the image, it will render the component without refreshing. I believe I have followed all the required steps as per the react-router-dom documentation, but I can't get the site to work if I include the tag.

I commented out a few sections as I initially thought I had implemented the ContextAPI incorrectly. Any help would be much appreciated.

Here's a snippet of my App.js file

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import { Header, Home } from './components'

import './App.css'

function App() {
    return (
        <div className='app'>
            <Header />
            <Router>
                <Routes>
                    <Route path='/' element={<Home />} />
                </Routes>
            </Router>
        </div>
    )
}

export default App

Here's the Home.jsx file:

import React from 'react'
import { Product } from '..'

import { heroLanding, products } from '../../constants'

import './Home.css'

const Home = () => {
    return (
        <div className='home'>
            <img src={heroLanding} alt='Landing Page' className='home__image' />

            <div className='home__row'>
                {products.map(
                    (product, index) =>
                        index < 2 && (
                            <Product
                                key={product.id}
                                title={product.title}
                                rating={product.rating}
                                price={product.price}
                                image={product.image}
                            />
                        )
                )}
            </div>
            <div className='home__row'>
                {products.map((product, index) =>
                    (index > 1) & (index < 5) ? (
                        <Product
                            key={product.id}
                            title={product.title}
                            rating={product.rating}
                            price={product.price}
                            image={product.image}
                        />
                    ) : null
                )}
            </div>
            <div className='home__row'>
                {products.map((product, index) =>
                    index > 4 ? (
                        <Product
                            key={product.id}
                            title={product.title}
                            rating={product.rating}
                            price={product.price}
                            image={product.image}
                        />
                    ) : null
                )}
            </div>
        </div>
    )
}

export default Home

Here's the Header.jsx file:

import React from 'react'
import { BsCart4 as BasketIcon, BsSearch as Search } from 'react-icons/bs'
import { Link } from 'react-router-dom'

import { logo } from '../../constants'
//import { useStateValue } from '../../contextAPI/StateProvider'

import './Header.css'

const Header = () => {
    // const [{ basket, user }, dispatch] = useStateValue()

    return (
        <div className='header'>
            <Link to='/'>
                <img src={logo} alt='Amazon Logo' className='header__logo' />
            </Link>

            <div className='header__search'>
                <input
                    className='header__search-input'
                    type='text'
                    placeholder='Search ...'
                />
                <span className='header__searchIcon'>
                    <Search className='header__searchIcon-icon' />
                </span>
            </div>

            <div className='header__nav'>
                <div className='header__option'>
                    <span className='header__option-lineOne'>Hello User</span>
                    <span className='header__option-lineTwoe'>Sign In</span>
                </div>
                <div className='header__option'>
                    <span className='header__option-lineOne'>Returns</span>
                    <span className='header__option-lineTwoe'>&amp; Orders</span>
                </div>
                <div className='header__option'>
                    <span className='header__option-lineOne'>Your</span>
                    <span className='header__option-lineTwo'>Prime</span>
                </div>
                <div className='header__option-basket'>
                    <BasketIcon />
                    <span className='header__option-lineTwo header__basketCount'>0</span>
                </div>
            </div>
        </div>
    )
}

export default Header

CodePudding user response:

You should put Router at the beginning of the return statement in App.js.

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import { Header, Home } from './components'

import './App.css'

function App() {
    return (
     <Router>
        <div className='app'>
            <Header />
            
                <Routes>
                    <Route path='/' element={<Home />} />
                </Routes>
            
        </div>
     </Router>
    )
}

export default App

CodePudding user response:

Issue

The issue with the code is that the header and links are rendered outside the router handling the routes. This means it's [Router] not aware of any external navigation actions above it in the React tree.

function App() {
  return (
    <div className='app'>
      <Header />
      <Router> // <-- routing context isn't aware of external actions
        <Routes>
          <Route path='/' element={<Home />} />
        </Routes>
      </Router>
    </div>
  )
}

Since you are using react-router-dom@6 you should certainly have some errors in the console warning you that the Link components have been rendered outside any routing context and to move them into one.

Solution

The Header component (and links) need to be moved into a router so they receive a proper routing context. You need only one router per app also, so go through your code and remove any extraneous routers you may have. This is so all RRD components use the same single routing context.

function App() {
  return (
    <div className='app'>
      <Router>
        <Header /> // <-- move inside routing context
        <Routes>
          <Route path='/' element={<Home />} />
        </Routes>
      </Router>
    </div>
  )
}

In most cases you will want to push the Router as high as possible in your application's ReactTree. It's common to wrap App in the index.js file so anything App is rendering will have the proper routing context available to it.

Example:

...
import { BrowserRouter as Router } from 'react-router-dom';
...

ReactDOM.render(
  <StrictMode>
    .... other context wrappers ....
      <Router>
        <App />
      </Router>
    .... other context wrappers ....
  </StrictMode>,
  rootElement
);
  • Related