2

I'm new to Redux, and I really don't have much time to spend researching, so I would appreciate if you could help me out. So basically I have a React component where I authenticate a user with an HTTP request to a backend. When I get the response back, I want the data to be saved in a Redux store so I can access it on other components/routes. How could this be done? Thank you.

This is my component:

class Register extends Component {
  constructor(props) {
    super(props);

    this.state = {
      errorMessage: null,
      user: null
    };
  }

  register = (event) => {
    event.preventDefault();

    console.log(event.target.email.value);
    let errorMessage = null;
    if (!event.target.name.value) errorMessage = 'Numele este obligatoriu.';
    else if (!event.target.email.value)
      errorMessage = 'Email-ul este obligatoriu.';

    else {
      const body = {
        name: event.target.name.value,
        email: event.target.email.value,
        password: event.target.password.value,
        confirmPassword: event.target.confirmPassword.value
      };

      return axios
        .post('http://localhost:5000/api/v1/auth/register', body)
        .then((response) => {
          console.log(response);
          this.setState({ // Instead of this, the user should be stored using Redux
            user: response.data.data.user
          });

        })
        .catch((error) => {
          this.setState({ errorMessage: error.response.data.message });
        });
    }
    this.setState({ errorMessage });
  };

  render() {
    return (
      <div className="register-page">
        <form onSubmit={this.register}>
          <h3>Cont nou</h3>
          <input type="text" placeholder="Nume" name="name" />
          <input type="text" placeholder="E-mail" name="email" />
          <input type="password" placeholder="Parola" name="password" />
          <input
            type="password"
            placeholder="Confirmă parola"
            name="confirmPassword"
          />
          <span className="error-message">{this.state.errorMessage}</span>
          <input type="submit" value="Trimite" name="submit" />
        </form>
      </div>
    );
  }
}

export default Register;
Robert Feduș
  • 274
  • 2
  • 13

1 Answers1

0

The fastest way if you need to save the authentification status of a user is to use useContext hooks.

  • create a Authcontext.js file and define what you will have in you context (but just the data type, you can see we do'nt need to define setIsAuthenticated here.
import React from 'react';

export default React.createContext({
  isAuthenticated: false,
  setIsAuthenticated: (value) => {},
});
  • In your main component you can now wrap you whole app with the Context. We define the setIsAuthenticated function and the initial value of isAuthenticated here.
const App = () => {

  const [isAuthenticated, setIsAuthenticated] = useState(AuthAPI.setupUser());


  return (
    <AuthContext.Provider value={{
      isAuthenticated,
      setIsAuthenticated
    }}>

    <AppContent />

    </AuthContext.Provider>
  );
};

ReactDOM.render(<App/>, document.getElementById('app'));

export default App;

As the context is a global state (as redux) you can also get the context from every component, for example.

import React, { useContext } from 'react';

const Logout = () => {
  const { setIsAuthenticated } = useContext(AuthContext);

  const logout = () => {
        AuthAPI.logout();
        setIsAuthenticated(false);
    };

   return(...)

To determine if the user is connected you have to build you own logic, but if you are using jwt, the setupUser could be something like this. It would be called every time the app starts to setup axios for your api call for example and return the status of thee user.

function setupUser() {
  // check if token exist
  const token = window.localStorage.getItem('authToken');
  if (token) {
    const { exp: expirationDate } = jwtDecode(token);

    if (expirationDate * 1000 > new Date().getTime()) {
      axios.defaults.headers['Authorization'] = 'Bearer ' + token;
      return true;
    } 
  } 
  return false;
}
A. Ecrubit
  • 489
  • 2
  • 15
  • Where does AuthAPI come from? – Robert Feduș May 02 '20 at 12:25
  • I added an example for you to better understand. – A. Ecrubit May 02 '20 at 12:35
  • I actually ended up using Context instead of Redux. Thank you for your answer, but one more question: isn't it unsafe to store jwt in localStorage? – Robert Feduș May 02 '20 at 13:52
  • Using redux you mean ? No it's not because everybody can decode a jwt token using `https://jwt.io/` for example and in a jwt token only general informations as the name, email or the role are encoded. – A. Ecrubit May 02 '20 at 15:51
  • Yeah, but localStorage can be accessed with XSS attacks. That was my point. So I would go with cookies instead. – Robert Feduș May 02 '20 at 16:04
  • Cookies are vulnerable to `CSRF` attacks, jwt are commonly store in the localStoare because it is only needed by the client side. Both have pros and cons, you can read more here : https://stackoverflow.com/questions/3220660/local-storage-vs-cookies – A. Ecrubit May 02 '20 at 16:12