1
votes

I am new to react and creating a simple log in feature, and came across a problem. I put a sign in / register / sign out button inside the NavBar, and I intended to control the login status in App component's state(initially true for testing purposes).

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      isLoggedIn: true,
    };
  }

  onSignOut = () => {
    this.setState({ isLoggedIn: false });
  };

  render() {
    const { posts, isLoggedIn } = this.state;
    console.log(1);
    return (
      <Router>
        **<NavBar isLoggedIn={isLoggedIn} onSignOut={this.onSignOut} />**
        <Switch>
          <Route path="/" exact component={Home}></Route>
          <Route path="/about"></Route>
          <Route path="/forum">
            <Forum posts={posts} />
          </Route>
          <Route path="/login"></Route>
          <Route path="/register">
            <Register />
          </Route>
          <Route path="/signin">
            <Signin />
          </Route>
        </Switch>
      </Router>
    );
  }
}

but when I update the state using onSignOut function which calls this.setState in NavBar, isLoggedIn changes to false, but if go back to home or any other page, isLoggedIn is turned back to true. I assume it's because App component rerenders when I go to another page. Is there any way to keep isLoggedIn unchanged unless its changed from this.setState?

const NavBar = ({ isLoggedIn, onSignOut }) => {
  const loginControl = !isLoggedIn ? (
    <>
      <a className="link dim gray f6 f5-ns dib mr3" href="/signin">
        Sign In
      </a>
      <a className="link dim gray f6 f5-ns dib mr3" href="/register">
        Register
      </a>{" "}
    </>
  ) : (
    **<p className="link dim gray f6 f5-ns dib" onClick={onSignOut}>
      Sign Out
    </p>**
  );
  return (
    <nav className="pa3 pa4-ns ttu">
      <a className="link dim black b f6 f5-ns dib mr3" href="/">
        Site Name
      </a>
      <a className="link dim gray f6 f5-ns dib mr3" href="/">
        Home
      </a>
      <a className="link dim gray f6 f5-ns dib mr3" href="/forum" title="Forum">
        Forum
      </a>
      {loginControl}
    </nav>
  );
};
1

1 Answers

0
votes

Assuming you are using react-router-dom, use a Link or NavLink and the to prop to push to new routes in your app. When you use an anchor tag it is a browser navigation, versus just an in-app navigation, and the app is reloaded.

const NavBar = ({ isLoggedIn, onSignOut }) => {
  const loginControl = !isLoggedIn ? (
    <>
      <Link className="link dim gray f6 f5-ns dib mr3" to="/signin">
        Sign In
      </Link>
      <Link className="link dim gray f6 f5-ns dib mr3" to="/register">
        Register
      </Link>{" "}
    </>
  ) : (
    **<p className="link dim gray f6 f5-ns dib" onClick={onSignOut}>
      Sign Out
    </p>**
  );
  return (
    <nav className="pa3 pa4-ns ttu">
      <Link className="link dim black b f6 f5-ns dib mr3" to="/">
        Site Name
      </Link>
      <Link className="link dim gray f6 f5-ns dib mr3" to="/">
        Home
      </Link>
      <Link className="link dim gray f6 f5-ns dib mr3" to="/forum" title="Forum">
        Forum
      </Link>
      {loginControl}
    </nav>
  );
};

Edit Routing Demo

Note: If you are using some other navigation package then use the corresponding version of Link available in that package.