1

When login success it redirects me to Main Page, but when I go to browser and open http://localhost:3000/MainPage it shows me Main Page (actually It must throw me to Login Page, because I am not logged in). In my case I can access Main Page without logging in by using url. What should I do in order to redirect unlogged users to LogIn page?

In my LogIn.js I am setting loggedIn state to false

App.js

class App extends Component {
render() {
return (
  <BrowserRouter>
   <Switch>
        <Route exact path="/" component={ LogIn }></Route>
        <Route path='/' component={ MainPage }></Route>
   </Switch>
  </BrowserRouter>
);
}
}

export default App; 

LogIn.js

const userIdRegex = RegExp(
/^[uU]*1+[0-9]*$/
);

class LogIn extends Component {

constructor(props) {
super(props);

this.state = {
  userId: null,
  password: null,
  fullName: undefined,
  responseError: false,
  loggedIn: false,
  formErrors: {
    userId: "",
    password: ""
  }
};
}

 handleSubmit = e => {
  e.preventDefault();

  axios.post('url', { 
   userId: 
  e.target.elements.userId.value,
  password: e.target.elements.password.value })
    .then((response) => {
      console.log(response);
      this.setState({ fullName: response.data.fullName, loggedIn: true });
      console.log(this.state.fullName);
      console.log(this.state.loggedIn);
    }).catch((error) => {
      console.log(error);
      this.setState({ responseError: true });
    });

  };
  handleChange = e => {
e.preventDefault();
const { name, value } = e.target;
let formErrors = { ...this.state.formErrors };

switch (name) {

  case "userId":
    formErrors.userId = userIdRegex.test(value)
      ? ""
      : "Invalid user ID";
    break;
  case "password":
    formErrors.password =
      value.length < 8 ? "Invalid password" : "";
    break;
  default:
    break;
}

this.setState({ formErrors, [name]: value }, () => 
  console.log(this.state));
  };
 render() {
const { formErrors } = this.state;
const responseError = this.state.responseError;
// const loggedIn = this.state.loggedIn;
// const { from } = this.props.location.state || '/';
if (this.state.loggedIn == true) {
  return <Redirect to="./MainPage" />;
}
return (
  <div className="wrapper">
    <div className="form-wrapper">
    <img src={Logo} className="App-logo" alt="Logo" />
    <p>To Log In enter your user ID and password.</p>
      <form onSubmit={this.handleSubmit} noValidate>      
        <div className="userId">
          <input
            autoFocus
            className={formErrors.userId.length > 0 ? "error" : null}
            placeholder="User ID"
            type="text"
            name="userId"
            noValidate
            defaultValue="u"
            onChange={this.handleChange}
          />
          {formErrors.userId.length > 0 && (
            <span className="errorMessage">{formErrors.userId}</span>
          )}
        </div>
        <div className="password">
          <input
            className={formErrors.password.length > 0 ? "error" : null}
            placeholder="Password"
            type="password"
            name="password"
            noValidate
            onChange={this.handleChange}
          />
          {formErrors.password.length > 0 && (
            <span className="errorMessage">{formErrors.password}</span>
          )}
        </div>
        <div className="createAccount">
          <button type="submit" disabled={!this.state.userId} disabled= 
 {!this.state.password}>Log in</button>
        </div>
      </form>
      { responseError==true && (
        <span className="response-error errorMessage">Please enter valid 
  user values</span>
      ) }
    </div>

  </div>
  )}
 }

export default LogIn;

MainPage.js

class MainPage extends Component {
state = {
    loggedIn: false
}

render(){
    if (this.state.loggedIn) {
        return <Redirect to="/" />;
    }
    console.log(this.state);
    return(
    <div>
        <p>Welcome</p>
    </div>

    );
}
}
export default MainPage;
  • Hey, my recommendation would be to check out redux, it will help you with state management. So you don't have to pass around the isLoggedIn state from main page to login page. Redux can have a single source of truth – Shivam Gupta Feb 15 '19 at 16:08

2 Answers2

0

It seems like you have the reverse in place in your main.js component. In you’re if statement you will want to check !this.state.loggedIn and then use

<Redirect to=‘’./LoginPage”/>

just like you did in the login component. The problem I see here (and maybe I’m missing something) is that the MainPage’s state.loggedIn will be set to false even when being redirected from after a Log In. You can pass the loggedIn variable from the LoginPage to the MainPage by using

<Redirect to={{pathname: “./MainPage”,  state: {loggedIn: this.state.loggedIn}}} \>

Then you can access whether the user has actually logged in with this.props.location.state.loggedIn within the MainPage component.

The way you currently have it within the main page, since the state.loggedIn is defaulting to false and you’re if condition checks whether or not loggedIn is true, it would make sense that it is never triggered.

IRTrapGod
  • 101
  • 2
  • 6
  • } \> this gives an error (three dots before closing tag). And where in LogIn.js I should place it? – Bositkhon Sultonov Feb 15 '19 at 18:34
  • @BositSultanov the three dots are where the rest of your props would go if you had any, sorry for the confusion. It would just go inside your if(this.state.loggedIn == true) statement in render, in place of the return that you have – IRTrapGod Feb 15 '19 at 18:37
  • I have got an error "Line 78: Expected an assignment or function call and instead saw an expression no-unused-expressions" In line 78 I have } /> In MainPage.js I have set state = { loggedIn: this.props.loggedIn } – Bositkhon Sultonov Feb 15 '19 at 18:52
  • @BositSultanov This is my bad, I was thinking of the Route component. I edited my original answer to be used with Redirect. That should now work per a previous answer https://stackoverflow.com/questions/52064303/reactjs-pass-props-with-redirect-component – IRTrapGod Feb 15 '19 at 22:48
0

A good aproach would be to create a custom Route to handle if the user is auth, an if it isnt auth, you redirect to Login.

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route { ...rest }
    render={props => {
      if ( isLogged()  ) {
           return <Component {...props} />;
      } else {
          return <Redirect to={{pathname:'/login'}} />;
      }
    }}
  />
);

Ricardo Gonzalez
  • 1,590
  • 1
  • 10
  • 22