Using React Context and now my navbar is gone?

Viewed 199

Just learned about react context yesterday, I had some issues with props starting to get undefined in child components. So alot of the props that were being passed down I made into contexts and that solved that issue.

Maybe I'm wrong but my understanding was whenever I make a context in a component, I need to import that component into my App.js and wrap my app in that component. When I started doing this, my navbar just doesn't render anymore. And it causes my react-router-dom to not work properly. When I click a link to route to the new component, it does route..but it mounts the component inside the parent component.

What am I doing wrong? Banging my head on this one.

Edit: Here is my full App.js

FeedIndexProvider, FeedDisplayProvider, and FeedCardProvider are just imports of those components.

import React, { useState, useEffect } from "react";
import "./App.css";
import "antd/dist/antd.css";
import Auth from "./components/Auth/Auth";
import MainLayout from "./components/Site/Layout";
import FeedIndexProvider from "./components/Feed/FeedIndex";
import FeedDisplayProvider from "./components/Feed/FeedDisplay";
import FeedCardProvider from "./components/Feed/FeedCard";
export const TokenContext = React.createContext();

function App() {
  const [token, setToken] = useState("");
  const [firstName, setFirstName] = useState("");
  const [userId, setUserId] = useState();

  useEffect(() => {
    if (localStorage.getItem("token")) {
      setToken(localStorage.getItem("token"));
    }
  }, []);

  useEffect(() => {
    if (localStorage.getItem("firstName")) {
      setFirstName(localStorage.getItem("firstName"));
    }
  }, []);

  useEffect(() => {
    if (localStorage.getItem("id")) {
      setUserId(localStorage.getItem("id"));
    }
  });

  const updateToken = (newToken) => {
    localStorage.setItem("token", newToken);
    setToken(newToken);
  };

  const updatedFirstName = (newFirstName) => {
    localStorage.setItem("firstName", newFirstName);
    setFirstName(newFirstName);
    console.log(firstName);
  };

  const updatedUserId = (newId) => {
    localStorage.setItem("id", newId);
  };

  const clearToken = () => {
    localStorage.clear();
    setToken("");
  };

  const protectedViews = () => {
    return (token === localStorage.getItem("token")) |
      (localStorage.getItem("token") === !undefined) ? (
      <TokenContext.Provider value={token}>
        <FeedIndexProvider>
          <FeedDisplayProvider>
            <FeedCardProvider>
              <MainLayout clickLogout={clearToken} />
            </FeedCardProvider>
          </FeedDisplayProvider>
        </FeedIndexProvider>
      </TokenContext.Provider>
    ) : (
      <Auth
        updateToken={updateToken}
        updatedFirstName={updatedFirstName}
        updatedUserId={updatedUserId}
      />
    );
  };

  return <div className="App">{protectedViews()}</div>;
}

export default App;

Here is my MainLayout which calls the Navbar:

const MainLayout = ({ clickLogout}) => {
  return (
    <Router>
      <Layout className="mainLayout">
        <Header>
          <Nav clickLogout={clickLogout} />
        </Header>
        <div className="spacer"></div>
        <Content>
          <div className="container-fluid">
            <div className="content">
              <Switch>
                <Route exact path="/">
                  <FeedIndex />
                </Route>
                <Route path="/post" component={ViewPost} />
              </Switch>
            </div>
          </div>
        </Content>
      </Layout>
    </Router>
  );
};

Update, here is my Nav

import React, { useState } from "react";
import { Link as RouterLink, BrowserRouter as Router } from "react-router-dom";
import { Anchor, Drawer, Button } from "antd";

const { Link } = Anchor;

const Nav = ({ clickLogout }) => {
  const [visible, setVisible] = useState(false);
  const showDrawer = () => {
    setVisible(true);
  };
  const onClose = () => {
    setVisible(false);
  };

  return (
    <div className="routing">
      <div className="container-fluid">
        <div className="header">
          <div className="logo">
            <img
              src="../../assets/mobile-shield.png"
              alt=""
              height="25px"
              style={{ borderRadius: "50%", marginRight: "5px" }}
            />
            <a href="https://google.com">EFA</a>
          </div>
          <div className="mobileHidden">
            <Anchor targetOffset="65">
              <RouterLink to="/">
                <a onClick={clickLogout}></a>
              </RouterLink>
            </Anchor>
          </div>
          <div className="mobileVisible">
            <Button type="primary" onClick={showDrawer}>
              <i className="fas fa-bars"></i>
            </Button>
            <Drawer
              placement="right"
              closable={false}
              onClose={onClose}
              visible={visible}
            >
              <Anchor targetOffset="65">
                <RouterLink to="/">
                  <a onClick={clickLogout}></a>
                </RouterLink>
              </Anchor>
            </Drawer>
          </div>
        </div>
      </div>
    </div>
  );
};
export default Nav;

1 Answers

Change this:

const FeedIndex = (props) => {
           ...
        
      return (
        <GetPostsContext.Provider value={getPosts}>
          <PostsContext.Provider value={posts}>
            <CreateReplyContext.Provider value={createReply}>
              <ReplyActiveContext.Provider value={replyActive}>
                <PostActiveContext.Provider value={postActive}>
                  <CreatePostContext.Provider value={createPost}>
                    <AddPostContext.Provider value={addPost}>
                      <PostOnContext.Provider value={postOn}>
                        <PostOffContext.Provider value={postOff}>
                          <AddReplyContext.Provider value={addReply}>
                            <ReplyOnContext.Provider value={replyOn}>
                              <ReplyOffContext.Provider value={replyOff}>
                                {props.children}
                              </ReplyOffContext.Provider>
                            </ReplyOnContext.Provider>
                          </AddReplyContext.Provider>
                        </PostOffContext.Provider>
                      </PostOnContext.Provider>
                    </AddPostContext.Provider>
                  </CreatePostContext.Provider>
                </PostActiveContext.Provider>
              </ReplyActiveContext.Provider>
            </CreateReplyContext.Provider>
          </PostsContext.Provider>
        </GetPostsContext.Provider>
      );
    
 }
Related