skip to Main Content

I created an app using the Marvel API that searches characters, comics, events, series, and creators and displays their information. Everything is working properly except for the Menu.jsx component is not updating to the values that are in local storage. For example, if I search for the character "Wolverine", it sets the local storage "heroName" variable to "Wolverine," but then if I click the logo link or the "Heroes" link again, it doesn’t load this "heroName" into the page.

Here is the code in App.jsx:

export default function App() {

  return (
    <HashRouter>
      <Menu />
      <Routes>
        {/* Heroes */}
        <Route path={'/:hName'} element={<Home />} />
        <Route exact path={'/characters/:id/comics'} element={<HeroComics />} />
        <Route exact path={'/characters/:id/events'} element={<HeroEvents />} />
        <Route exact path={'/characters/:id/series'} element={<HeroSeries />} />
        <Route exact path={'/characters/:id/stories'} element={<HeroStories />} />
        {/* Comics */}
        <Route exact path={'/comics'} element={<ComicsPage />} />
        {/* Events */}
        <Route exact path={'/events'} element={<EventsPage />} />
        {/* Series */}
        <Route exact path={'/series'} element={<SeriesPage />} />
        {/* Stories */}
        <Route exact path={'/stories'} element={<StoriesPage />} />
        {/* Creators */}
        <Route path={'/creators/:cName'} element={<CreatorsPage />} />
        <Route exact path={'/creators/:id/comics'} element={<CreatorComics />} />
        <Route exact path={'/creators/:id/events'} element={<CreatorEvents />} />
        <Route exact path={'/creators/:id/series'} element={<CreatorSeries />} />
        <Route exact path={'/creators/:id/stories'} element={<CreatorStories />} />
      </Routes>
      <Footer />
    </HashRouter>
  );
}

Here is the code in Menu.jsx:

export default function Menu() {

    const [heroName, setHeroName] = useState("");
    const [creatorName, setCreatorName] = useState("");

    useEffect(() => {
        setHeroName(localStorage.getItem('heroName'));
        setCreatorName(localStorage.getItem('creatorName'));
    }, []);

    return (
        <Navbar expand="lg" sticky="top" className="nav-bar">
            <Container>
                <Navbar.Brand as={Link} to={`/${heroName}`} className="logo-text">Marvel App</Navbar.Brand>
                <Navbar.Toggle aria-controls="responsive-navbar-nav" />
                <Navbar.Collapse id="responsive-navbar-nav">
                    <Nav className="ml-auto">
                        <Nav.Link as={Link} to={`/${heroName}`}>Heroes</Nav.Link>
                        <Nav.Link as={Link} to={"/comics"}>Comics</Nav.Link>
                        <Nav.Link as={Link} to={"/events"}>Events</Nav.Link>
                        <Nav.Link as={Link} to={"/series"}>Series</Nav.Link>
                        {/* <Nav.Link as={Link} to={"/stories"}>Stories</Nav.Link> */}
                        <Nav.Link as={Link} to={`/creators/${creatorName}`}>Creators</Nav.Link>
                    </Nav>
                </Navbar.Collapse>
            </Container>
        </Navbar>
    )
}

Here is how I’m setting and getting local storage in Home.jsx:

useEffect(() => {
        localStorage.setItem('heroName', hName);
        const heroName = localStorage.getItem('heroName');
        setHeroName(heroName);
        handleClick(heroName);
    }, []);

    const handleShow = async (heroID) => {
        setShow(true);
        try {
            let data = await fetchCharactersByCharacterID(heroID);
            setHero(data.data.results);
        } catch (err) {
            return err;
        }
    }

    const handleClick = async (heroName) => {
        try {
            let data = await fetchCharacters(heroName);
            setHeroes(data.data.results);
            localStorage.setItem('heroName', heroName);
            navigate(`/${heroName}`);
        } catch (err) {
            return err;
        }
    }

2

Answers


  1. Chosen as BEST ANSWER

    I was able to fix this by getting Menu.jsx to reload on link click. Here is my new code:

    export default function Menu() {
    
        const heroName = localStorage.getItem('heroName');
        const creatorName = localStorage.getItem('creatorName');
    
        let navigate = useNavigate();
    
        function changeLocation(placeToGo) {
            navigate(placeToGo, { replace: true });
            window.location.reload();
        }
    
        return (
            <Navbar expand="lg" sticky="top" className="nav-bar">
                <Container>
                    <Navbar.Brand as={Link} to={`/${heroName}`} onClick={() => changeLocation(`/${heroName}`)} className="logo-text">Marvel App</Navbar.Brand>
                    <Navbar.Toggle aria-controls="responsive-navbar-nav" />
                    <Navbar.Collapse id="responsive-navbar-nav">
                        <Nav className="ml-auto">
                            <Nav.Link as={Link} to={`/${heroName}`} onClick={() => changeLocation(`/${heroName}`)}>Heroes</Nav.Link>
                            <Nav.Link as={Link} to={"/comics"} onClick={() => changeLocation("/comics")}>Comics</Nav.Link>
                            <Nav.Link as={Link} to={"/events"} onClick={() => changeLocation("/events")}>Events</Nav.Link>
                            <Nav.Link as={Link} to={"/series"} onClick={() => changeLocation("/series")}>Series</Nav.Link>
                            {/* <Nav.Link as={Link} to={"/stories"}>Stories</Nav.Link> */}
                            <Nav.Link as={Link} to={`/creators/${creatorName}`} onClick={() => changeLocation(`/creators/${creatorName}`)}>Creators</Nav.Link>
                        </Nav>
                    </Navbar.Collapse>
                </Container>
            </Navbar>
        )
    }
    

  2. In your Menu.jsx you’re using useEffect only once, when the component is rendering and therefore it’s not changing when you change the localStorage value.

    Try add localStorage to the useEffect dependencies.

    i.e.

    useEffect(() => {
        setHeroName(localStorage.getItem('heroName'));
        setCreatorName(localStorage.getItem('creatorName'));
    
    }, [localStorage]); // or localStorage.getItem('heroName')
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search