0

I'm trying to setup a url that changes depending on the useState. I'm doing this because I want to be able to access both states with the url. So this is what my router file looks like:

import React from 'react';
import {BrowserRouter as Router, Switch, Route} from "react-router-dom";


function router(){
    return (
            <Router>
                <Switch>
                    <Route path="/restaurant/:toggleParameter" children={<Restaurant/>}/>
                </Switch>
            </Router>
        );
    }


export default router;

An the component Restaurant looks like this:

import React, {useEffect, useState} from 'react';
import {useParams,Redirect} from "react-router-dom";
function RestaurantLandingPage(){


    const {toggleParameter} = useParams();
    console.log("Parameter");
    console.log(toggleParameter);

    const [profileToggle,setProfileToggle] = useState(toggleParameter);

    const restaurantID =localStorage.getItem("restaurantId");
    console.log(restaurantID);

    const changeParameterToProfile =()=>{
        setProfileToggle("profile");
    };

    const changeParameterToMenu=()=>{
        setProfileToggle("menu");
    }
        return (
            <div id="wrapper">
                <div className="restaurantHover">
                    <button
                        className="switchButton"
                        onClick={()=>{changeParameterToProfile()}}
                        style={profileToggle==="profile"? {textDecoration:'underline',textDecorationThickness:'3px',textDecorationColor:'#6C5AF2'}:{}}
                    >
                        Profile
                    </button>
                    <button
                        className="switchButton"
                        onClick={changeParameterToMenu}
                        style={profileToggle==="menu"?{textDecoration:'underline',textDecorationThickness:'3px',textDecorationColor:'#6C5AF2'}:{}}
                    >
                        Menu
                    </button>
                    <div id="switchBottom"/>
                    {(profileToggle==="profile")&&(
                        <Contact profileToggle={profileToggle} changeParameterToMenu={changeParameterToMenu}/>
                    )}
                    {(profileToggle==="menu")&&(
                        <RestauarntMenuOverview/>
                    )}
                </div>
            </div>
        )}
}
export default RestaurantLandingPage;

The url-param "toggleParameter" is "profile" or "menu". I'll access it with useParams(). Now if I press the button Profile the url-param "toggleParameter" should switch to Profile and if I press the button Menu the url-param "toggleParameter" should switch to Menu. I thought I could use Redirect like this:

<button
className="switchButton"
onClick={()=>{changeParameterToProfile();
<Redirect to={/restaurant/{profileToggle}/>}}
style={profileToggle==="profile"? {textDecoration:'underline',textDecorationThickness:'3px',textDecorationColor:'#6C5AF2'}:{}}>
Profile
</button>

But this doesn't work. I'm a little bit confused with all the react-router possibilities because I haven't found the right one yet.

2 Answers 2

2

React doesn't allow updating the state when the component is unmounted & it will cause some serious memory leak hidden before your eyes. Also setState function is an Asynchrounus function & it can get called after the history.push method. Changing the route with history.push will unmount the component & in some cases setState might get called afterwards causing state update on unmounted component. Also the value of profileToggle will only get changed after setProfileToggle is called keeping the value of profileToggle same & history.push will also use the previous value & you or the user have to click the button twice to go to /restaurant/profile or /restaurant/menu

Code:

import {useParams,useHistory } from "react-router-dom";
function RestaurantLandingPage(){
   const history = useHistory()
   const {toggleParameter} = useParams(); 

  const changeParameterToProfile =()=>{
        history.push(`/restaurant/profile`)
    };

    const changeParameterToMenu=()=>{
        history.push(`/restaurant/menu`)
    }

  return(
        ...... 
        <button
         className="switchButton"
         onClick={()=>changeParameterToProfile()}
         style={toggleParameter==="profile"? 
                 { textDecoration:'underline',
                   textDecorationThickness:'3px',
                   textDecorationColor:'#6C5AF2'
                 }:{}
                }
         >
          Profile
        </button>
    ...... 
    ) 
}
Sign up to request clarification or add additional context in comments.

Comments

1

Try this

import {useParams,useHistory } from "react-router-dom";
function RestaurantLandingPage(){
   const history = useHistory()
   const {toggleParameter} = useParams(); 

  const changeParameterToProfile =()=>{
        setProfileToggle("profile");
        history.push(`/restaurant/${profileToggle} `)
    };

    const changeParameterToMenu=()=>{
        setProfileToggle("menu")
        history.push(`/restaurant/${profileToggle} `)
    }

  return(
        ...... 
        <button
         className="switchButton"
         onClick={()=>{changeParameterToProfile();}
         style={profileToggle==="profile"? {textDecoration:'underline',textDecorationThickness:'3px',textDecorationColor:'#6 
    C5AF2'}:{}}>
    Profile
    </button>
     <button
      className="switchButton"
     onClick={()=>{changeParameterToMenu();}
         style={profileToggle==="profile"? 
{textDecoration:'underline',textDecorationThickness:'3px',textDecorationColor:'#6 
     C5AF2'}:{}}>
     Menu
     </button>
    ...... 
    ) 
} 

Let me know if it works

5 Comments

this won't work either as the state of profileToggle will remain same until the function executes & also setState is asynchronus thus the callback to set the state might get called afterwards thus there will be a state update on a unmounted component which is a React-OP. React will complain about this in the console... Thus instead of using a separate state for the dynamic part of the url use just the hard coded profile or menu value to change routes.. See below:
Have you tried it and it didn't work! Try it if it didn't work tell me, here you are just complicating your code react-router-dom is easy to use and to implement try that one first then you conclude.
@Cirspen Gari It's not about how easy a library is, its about how the library works. Your solution should work but there will be some bugs later on. So I just pointed out those. I'm just suggesting & its not my problem. I didn't asked the question, right?
@CrispenGari thank you for your answer! I used KR Tirtho's solution but thank you anyway!
Okay enjoy coding buddy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.