title: Axios request not working with React + Redux
body: <p>I'll try to give a premise and then follow it up with the code.</p>
  
  <p>I decided to implement Material UI into my React project, and I got most of it going. How the app is set up, the user is faced with the Login page. The Login.js module renders the <a href="https://github.com/mui-org/material-ui/tree/master/docs/src/pages/getting-started/page-layout-examples/sign-in" rel="nofollow noreferrer">SignIn.js module</a>, enters their credentials, and clicks submit. The <code>formData</code>, <code>onChange</code> and <code>onSubmit</code> are passed as props to the SignIn component from the Login component -- and the Login component receives these via <code>mapStateToProps</code>. The Login component uses the connect middleware to link redux state to the react app.</p>
  
  <p>Clicking submit triggers the formData (in the Login component which are passed to the SignIn component) to hit my <code>login</code> method located in <code>"../../actions/auth";</code>. The error occurs from within this method, at the axios call in the try catch, where I attempt to communicate with the backend <code>const response = await axios.post("/api/auth", body, config);</code></p>
  
  <p>What's weird is that <code>dispatch({ type: LOGIN_SUCCESS, payload: response.data });</code> never gets hit, which is supposed to set the state to the token returned from the backend, as it seems that <code>LOGIN_SUCCESS</code> is never executed. But what's VERY weird is that console logging the token actually works! It just seems as through it's never stored, forcing AUTH_ERROR to get invoked instead.</p>
  
  <p>This is my Login component:</p>
  
  <pre><code> // Login.js
   import SignIn from "../../material/SignIn";
  
   const Login = ({ setAlert, login, isAuthenticated }) =&gt; {
   const [formData, setFormData] = useState({
   email: "",
   password: ""
   });
  
   const { email, password } = formData;
  
   const onChange = e =&gt; {
   setFormData({ ...formData, [e.target.name]: e.target.value });
   };
  
   const onSubmit = e =&gt; {
   login(email, password);
   };
   // Redirect if logged in
   if (isAuthenticated) {
   return &lt;Redirect to="/dashboard" /&gt;;
   }
  
   return (
   &lt;Fragment&gt;
        &lt;SignIn
        email={email}
        password={password}
        onSubmit={onSubmit}
        onChange={onChange}
        isAuthenticated={isAuthenticated}
        /&gt;
   &lt;/Fragment&gt;
   );
   };
  
   Login.propTypes = {
   setAlert: PropTypes.func.isRequired,
   login: PropTypes.func.isRequired,
   isAuthenticated: PropTypes.bool
   };
  
   const mapStateToProps = state =&gt; ({
   isAuthenticated: state.auth.isAuthenticated
   });
  
   export default connect(
   mapStateToProps,
   { setAlert, login }
   )(Login);
  </code></pre>
  
  <p>And the SignIn component that it is rendering is here:</p>
  
  <pre><code> // SignIn.js
   export default function SignIn({ email, password, onChange, onSubmit }) {
   const classes = useStyles();
  
   return (
   &lt;Container component="main" maxWidth="xs"&gt;
        &lt;CssBaseline /&gt;
        &lt;div className={classes.paper}&gt;
        &lt;Avatar className={classes.avatar}&gt;
             &lt;LockOutlinedIcon /&gt;
        &lt;/Avatar&gt;
        &lt;Typography component="h1" variant="h5"&gt;
             Sign in
        &lt;/Typography&gt;
        &lt;form onSubmit={e =&gt; onSubmit(e)} className={classes.form} noValidate&gt;
             &lt;TextField
             variant="outlined"
             margin="normal"
             required
             onChange={e =&gt; onChange(e)}
             fullWidth
             id="email"
             label="Email Address"
             name="email"
             value={email}
             // autoComplete="email"
             autoFocus
             /&gt;
             &lt;TextField
             variant="outlined"
             margin="normal"
             required
             onChange={e =&gt; onChange(e)}
             fullWidth
             name="password"
             label="Password"
             type="password"
             value={password}
             id="password"
             autoComplete="current-password"
             /&gt;
             &lt;FormControlLabel
             control={&lt;Checkbox value="remember" color="primary" /&gt;}
             label="Remember me"
             /&gt;
             &lt;Button
             type="submit"
             fullWidth
             variant="contained"
             color="primary"
             className={classes.submit}
             &gt;
             Sign In
             &lt;/Button&gt;
             &lt;Grid container&gt;
             &lt;Grid item xs&gt;
             &lt;Link href="#" variant="body2"&gt;
                  Forgot password?
             &lt;/Link&gt;
             &lt;/Grid&gt;
             &lt;Grid item&gt;
             &lt;Link href="#" variant="body2"&gt;
                  {"Don't have an account? Sign Up"}
             &lt;/Link&gt;
             &lt;/Grid&gt;
             &lt;/Grid&gt;
        &lt;/form&gt;
        &lt;/div&gt;
        &lt;Box mt={5}&gt;
        &lt;MadeWithLove /&gt;
        &lt;/Box&gt;
   &lt;/Container&gt;
   );
   }
  </code></pre>
  
  <p>Clicking the submit button raises the <code>onSubmit</code> method in my Login component:</p>
  
  <pre><code> // Login user
   export const login = (email, password) =&gt; async dispatch =&gt; {
   // Config needed because we're sending data
   const config = {
   headers: {
        "Content-Type": "application/json"
   }
   };
  
   const body = JSON.stringify({ email, password });
  
   try {
   const response = await axios.post("/api/auth", body, config);
  
   // Skips over this dispatch
   dispatch({
        type: LOGIN_SUCCESS,
        payload: response.data
   });
  
   // But hits this dispatch.. and then console logs 'REACHED' as seen below
   dispatch(loadUser());
   } catch (err) {
   const errors = err.response.data.errors;
  
   if (errors) {
        errors.forEach(error =&gt; {
        dispatch(setAlert(error.msg, "danger"));
        });
   }
  
   dispatch({
        type: LOGIN_FAIL
   });
   }
   };
  </code></pre>
  
  <p>If you notice, after the axios call, <code>loadUser is called</code>, defined as:</p>
  
  <pre><code> // Load user
   export const loadUser = () =&gt; async dispatch =&gt; {
   const token = localStorage.token;
  
   console.log('REACHED!'); // reached
  
   if (token) {
   setAuthToken(token);
   }
  
   try {
   const response = await axios.get("/api/auth");
  
   dispatch({
        type: USER_LOADED,
        payload: response.data
   });
   } catch (err) {
   dispatch({
        type: AUTH_ERROR // This is dispatched
   });
   }
   };
  </code></pre>
  
  <p>The backend route is the following:</p>
  
  <pre><code> // @route  POST api/auth
   // @desc   Authenticate user and get token
   // @access Public
   router.post(
   "/",
   [
   check("email", "Please include a valid email").isEmail(),
   check("password", "Please is required").exists()
   ],
   async (req, res) =&gt; {
   const errors = validationResult(req);
  
   // send back any errors
   if (!errors.isEmpty()) {
        return res.status(400).json({
        errors: errors.array()
        });
   }
  
   const { email, password } = req.body;
  
   try {
        // check if user exists, send error if so
        let user = await User.findOne({ email });
  
        if (!user) {
        return res
             .status(400)
             .json({ errors: [{ msg: "Invalid credentials" }] });
        }
  
        const isMatch = await bcrypt.compare(password, user.password);
  
        if (!isMatch) {
        return res
             .status(400)
             .json({ errors: [{ msg: "Invalid credentials" }] });
        }
        // return jsonwebtoken so that way they're logged in right
        // away, without having to log in after registering
        const payload = {
        user: {
             id: user.id
        }
        };
  
        jwt.sign(
        payload,
        config.get("jwtSecret"),
        {
             expiresIn: process.env.PORT ? 3600 : 36000
        },
        (err, token) =&gt; {
             if (err) throw err;
  
             console.log(token); // prints token!
  
             return res.json({ token });
        }
        );
   } catch (err) {
        console.log(err);
        res.status(500).send("Server error");
   }
   }
   );
  </code></pre>
  
  <p>I'm so confused at this point. The token is being rendered but it seems as though React doesn't 'await' the response before Node gets a chance to send it back.</p>