React router - link to another component does not work

Hi,
I have a problem with link to another component. I have 3 components “Base”, “Toppings” and “Order”. After “Order” I wanted to add “ContactForm” component to fill in client’s contact info and then on submit redirect to home page to make another order. In the App.js file I filled in element the same way as the other 3 components but when I click the button on contact form to redirect me to to “Order” component nothing happens. Even if I moved the “ContactForm” component before “Order” or before “Base” component the problem still occurs.

App.js

import React, { useState } from 'react';
import { Route, Switch, useLocation } from "react-router-dom";
import Home from './components/Home';
import Base from './components/Base';
import Toppings from './components/Toppings';
import Order from './components/Order';
import { AnimatePresence} from 'framer-motion';
import Modal from './components/Modal';
import ContactForm from './components/ContactForm';


function App() {
  // get information about the current route location, whenever route changes it will update the information stored in this constant
  // we have to pass this information to switch component and it will understnand when rout changes and what
  // that to do with exit animation
  const location = useLocation();
  const [pizza, setPizza] = useState({ base: "", toppings: [], price:[] });
  const [showModal, setShowModal] = useState(false);
  
  const addBase = (base) => {
    setPizza({ ...pizza, base});
    console.log("Pizza base: "+ base.name);
    console.log("Pizza object Base" + base.name);
    console.log("Pizza object Base :Price" + base.price);
    console.log("Pizza object Base id" + base.id);
  }
  
  const addTopping = (topping) => {
    let toppingsPrice;
    let newToppings;
    if(!pizza.toppings.includes(topping)){
      newToppings = [...pizza.toppings, topping];
      toppingsPrice = [...pizza.price, topping.price]
      console.log("toppingsprice" + toppingsPrice);
    } else {
      newToppings = pizza.toppings.filter(item => item !== topping)
      toppingsPrice = pizza.toppings.filter(item => item !== topping.price)
      console.log("toppingsprice" + toppingsPrice);
    }
    setPizza({ ...pizza, toppings: newToppings , price: toppingsPrice});
    console.log("toppings" + newToppings.length)
    console.log("toppings" + newToppings[0].id)
    console.log("toppings" + newToppings[0].name)
    console.log("toppings" + newToppings[0].price)
    console.log("czy cos jest w toppings price"+ toppingsPrice);
  }

  
  return (
    <>
    <Modal showModal={showModal} setShowModal={setShowModal} />
      <AnimatePresence exitBeforeEnter onExitComplete={()=>setShowModal(false)}>
        <Switch location={location} key={location.key}>
          <Route path="/base">
            <Base addBase={addBase} pizza={pizza} />
          </Route>
          <Route path="/toppings">
            <Toppings addTopping={addTopping} pizza={pizza}/>
          </Route>
          <Route path="/order">
            <Order pizza={pizza} setShowModal={setShowModal} />
          </Route>
          <Route path="/contact">
            <ContactForm />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </AnimatePresence>
    </>
  );
}
export default App

Topping.js where button to redirect to ContactForm is located

import React from 'react';
import { Link } from 'react-router-dom';
import {motion} from 'framer-motion';
import dataToppings from '../data/toppingsData.json';
import '../styles/toppings_styles.css';

const toppingsContainerVariants={
  animateFrom:{
    opacity: 0,
    x:'100vh'
  },
  animateTo:{
    x:0,
    opacity:1,
    transition:{
      type:'spring', delay:0.5
    }
  },
  hover: {
    scale: 1.1,
    textShadow: "0px 0px 8px rgb(255,255,255)",
    boxShadow: "0px 0px 8px rgb(255,255,255)",
    transition: {
      duration: 0.3,
      yoyo: Infinity
    }
  }, 
  exit:{
    x:'-100vw',
    transition:{ease:'easeInOut'}
  }
}

const Toppings = ({ addTopping, pizza }) => {
  let toppingsObject = dataToppings;
      
  return (
    <motion.div variants={toppingsContainerVariants} exit="exit" initial="animateFrom" animate="animateTo" className="toppings-container">
      <div className="toppings-h3-container-style">
        <h3 className="style-h3">Step 2: Choose Toppings</h3>
      </div>
      <ul className="toppings-element-container">
        {toppingsObject.map(topping => {
          let spanClass = pizza.toppings.includes(topping) ? 'active' : '';
          let liElementClass = pizza.toppings.includes(topping) ? 'active-element' : 'toppings-list-element';
          return (
              <motion.li className={liElementClass} key={topping} onClick={() => addTopping(topping)}>
                <img className="toppings-icon-style" src={topping.icon} alt={topping.name}/>
                <span className={spanClass}>{ topping.name }</span>
              </motion.li>
          )
        })}
      </ul>

      <Link to="/contact">
        <motion.button variants={toppingsContainerVariants} className="base-button-style" whileHover="hover">
          Contact Form
        </motion.button>
      </Link>

    </motion.div>
  )
}

export default Toppings;

Thanks in advance

I’ve only used react-router a few times, but I think to make it work, you’ll also have to import BrowserRouter and wrap your whole App component like this:

import { BrowserRouter, Route, Switch, useLocation } from "react-router-dom";

function App(){
  return (
    <BrowserRouter>
      <Route path="/">
        {...}
      </Route>
      <Route path="/base">
        {...}
      </Route>
    </BrowserRouter>
  )
}
1 Like

Did you manage to solve this?

Because there should also be an error like You should not use <Switch> outside a <Router>.