Search code examples
reactjsreact-routerreact-bootstrapreact-bootstrap-nav

Route stays the same with links platform/:id in Navbar dropdown item React react-bootstrap


I want to achieve the link= /platform/:id each time the navbar dropdown item is selected. instead i get /platform/:id/platform:id

code for the Header.js:

import React from 'react'
import { Route } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { LinkContainer } from 'react-router-bootstrap'
import { Navbar, Nav, Container, NavDropdown } from 'react-bootstrap'
import SearchBox from './SearchBox'
import { logout } from '../actions/userActions'

const Header = () => {
  const dispatch = useDispatch()

  const userLogin = useSelector((state) => state.userLogin)
  const { userInfo } = userLogin

  const logoutHandler = () => {
    dispatch(logout())
  }

  return (
    <header>
      <Navbar bg='dark' variant='dark' expand='lg' collapseOnSelect>
        <Container>
          <LinkContainer to='/'>
            <Navbar.Brand>ProShop</Navbar.Brand>
          </LinkContainer>
          <Navbar.Toggle aria-controls='basic-navbar-nav' />
          <Navbar.Collapse id='basic-navbar-nav'>
            <Route render={({ history }) => <SearchBox history={history} />} />
            <Nav className='ml-auto'>
              <NavDropdown title='Nintendo' id='nintendomenu' to='/category/nintendo'>
                <LinkContainer to='platform/nintendo3ds'>
                  <NavDropdown.Item>Nintendo 3ds</NavDropdown.Item>
                </LinkContainer>
                
                <LinkContainer to='platform/nintendo2ds'>
                  <NavDropdown.Item>Nintendo 2ds</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/nintendods'>
                  <NavDropdown.Item>Nintendo 2ds</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/nintendoswii'>
                  <NavDropdown.Item>Nintendo Wii</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/nintendowiiu'>
                  <NavDropdown.Item>Nintendo Wii U</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/nintendoswitch'>
                  <NavDropdown.Item>Nintendo Switch</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/nintendoswitchlite'>
                  <NavDropdown.Item>Nintendo Switch Lite</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/gameboy'>
                  <NavDropdown.Item>Nintendo Gameboy</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/supernintendo'>
                  <NavDropdown.Item>Nintendo Super</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/nintendo64'>
                  <NavDropdown.Item>Nintendo 64</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/nintendods'>
                  <NavDropdown.Item>Nintendo DS</NavDropdown.Item>
                </LinkContainer>
              </NavDropdown>

              <NavDropdown title='playstation' id='playstation'>
                <LinkContainer to='platform/playstation1'>
                  <NavDropdown.Item>Playstation</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/playstation2'>
                  <NavDropdown.Item>Playstation 2</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/playstation3'>
                  <NavDropdown.Item>Playstation 3</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/playstation4'>
                  <NavDropdown.Item>Playstaion 4</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/playstation5'>
                  <NavDropdown.Item>Playstation 5</NavDropdown.Item>
                </LinkContainer>
              </NavDropdown>

              <NavDropdown title='xbox' id='' to=''>
                <LinkContainer to='platform/xbox1'>
                  <NavDropdown.Item>Xbox</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer>
                  <NavDropdown.Item to='platform/xbox360'>Xbox 360</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer>
                  <NavDropdown.Item   to='platform/xboxone'>Xbox One</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/xboxseriesx'>
                  <NavDropdown.Item>Xbox Series X</NavDropdown.Item>
                </LinkContainer>
                <LinkContainer to='platform/xboxseriess'>
                  <NavDropdown.Item>Xbox Series S</NavDropdown.Item>
                </LinkContainer>
              </NavDropdown>


              <LinkContainer to='/cart'>
                <Nav.Link>
                  <i className='fas fa-shopping-cart'></i> Cart
                </Nav.Link>
              </LinkContainer>
              {userInfo ? (
                <NavDropdown title={userInfo.name} id='username'>
                  <LinkContainer to='/profile'>
                    <NavDropdown.Item>Profile</NavDropdown.Item>
                  </LinkContainer>
                  <NavDropdown.Item onClick={logoutHandler}>
                    Logout
                  </NavDropdown.Item>
                </NavDropdown>
              ) : (
                <LinkContainer to='/login'>
                  <Nav.Link>
                    <i className='fas fa-user'></i> Sign In
                  </Nav.Link>
                </LinkContainer>
              )}
              {userInfo && userInfo.isAdmin && (
                <NavDropdown title='Admin' id='adminmenu'>
                  <LinkContainer to='/admin/userlist'>
                    <NavDropdown.Item>Users</NavDropdown.Item>
                  </LinkContainer>
                  <LinkContainer to='/admin/productlist'>
                    <NavDropdown.Item>Products</NavDropdown.Item>
                  </LinkContainer>
                  <LinkContainer to='/admin/orderlist'>
                    <NavDropdown.Item>Orders</NavDropdown.Item>
                  </LinkContainer>
                </NavDropdown>
              )}
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>
    </header>
  )
}

export default Header

Route for /platform/:id in App.js:

<Route path="/platform/:id" component={HomeScreen} />

What i want to achieve: http://localhost:3000/platform/xboxone , when the xboxone is selected http://localhost:3000/platform/xbox360, when xbox360 is selected right after the xboxone

What i get currently: http://localhost:3000/platform/xboxone , when the xboxone is selected http://localhost:3000/platform/platform/xbox360, when xbox360 is selected right after the xboxone

Please help thank you!

Edit: So, as i said whenever i select the Nav.Dropdown.Item, i get the result for example: if i select Nav.Dropdown.Item playstation3, it goes to http://localhost:3000/platform/playstation3, which i what i need.

NOw, after http://localhost:3000/platform/playstation2, if i select another Nav.Dropdown.Item playstation2, it goes to http://localhost:3000/platform/playstation3/platform/playstation2

instead i want to go to http://localhost:3000/platform/playstation2, whenever another nav dropdown item is selected.

HomeScreen.js :

import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col } from 'react-bootstrap'
import Product from '../components/Product'
import Message from '../components/Message'
import Loader from '../components/Loader'
import Paginate from '../components/Paginate'
import ProductCarousel from '../components/ProductCarousel'
import Meta from '../components/Meta'
import { listProducts } from '../actions/productActions'

const HomeScreen = ({ match }) => {
  const keyword = match.params.keyword
  const [sortOrder, setSortOrder] = useState('');
  //const category = match.params.id ? match.params.id : '';
  const platform = match.params.id ? match.params.id : ''; 
  const pageNumber = match.params.pageNumber || 1

  const dispatch = useDispatch()

  const productList = useSelector((state) => state.productList)
  const { loading, error, products, page, pages } = productList

  useEffect(() => {
    dispatch(listProducts(platform, keyword, pageNumber, sortOrder))
  }, [dispatch, keyword, pageNumber, sortOrder])
  

  const sortHandler = (e) => {
    setSortOrder(e.target.value);
    dispatch(listProducts(platform, keyword, sortOrder));
  };


  return (
    <>
      <Meta />
      {!keyword ? (
        <ProductCarousel />
      ) : (
        <Link to='/' className='btn btn-light'>
          Go Back
        </Link>
      )}
      {/*category && <h2>{category}</h2>*/}
      <ul className="filter">
        <li>
          Sort By{' '}
          <select name="sortOrder" onChange={sortHandler}>
            <option value="">Newest</option>
            <option value="lowest">Lowest</option>
            <option value="highest">Highest</option>
          </select>
        </li>
      </ul>
      {loading ? (
        <Loader></Loader>
      ) : error ? (
        <Message>{error}</Message>
      ) : (
        <>
          <Row>
            {products.map((product) => (
              <Col key={product._id} xs={6} sm={12} md={6} lg={4} xl={3}>
                <Product product={product} />
              </Col>
            ))}
          </Row>
          {/*<Paginate
            pages={pages}
            page={page}
            keyword={keyword ? keyword : ''}
          />*/}
        </>
      )}
    </>
  )
}

export default HomeScreen


Solution

  • So for your previous question, i guess it is figured out that we use

    <LinkContainer to='/platform/nintendowiiu'> 
    
     // instead of
    <LinkContainer to='platform/nintendowiiu'>
    

    Now to address another issue that is your content should change you should make use of useParams. You can get URL parameters and set your state accordingly. This will cause your component to re-render and no need to refresh the page.

    For using useParams you can just simply do the following

    // First import
    import { useParams } from "react-router-dom";
    
    // Then use it in your component
    const { platformId } = useParams();
    

    The platformId is the name of variable that you might have used white you have set up your routes. So basically whatever you have set up as a variable after the colon.

    <Route path="/platform/:platformId" component={HomeScreen} />