How to pass status codes to client side? (Redux asyncThunk)

Issue

I want to access the status sent from my Express server in my React component. I am using redux to dispatch a login fetch request and want to conditionally render different childrens based on the status code received (eg. ‘Incorrect Password’ if status code 401)

loginmodal.js

    const handleLogin = async (event) => {
        event.preventDefault();
        let result = await dispatch(login({ email, password }))
        console.log(result) //payload is undefined if incorrect password.
    }

userAuthSlice.js (Redux)

export const login = createAsyncThunk(
    'userAuth/login',
    async (payload, thunkAPI) => {
        const { email, password } = payload
        const result = await fetch(
            loginPath, {
            mode: 'cors',
            credentials: 'include',
            method: 'post',
            body: JSON.stringify({ email, password }),
            headers: {
                'Content-Type': 'application/json'
            },
        }
        )
        console.log(result) // Response {type: 'cors', url: 'http://localhost:5000/login', redirected: false, status: 401, ok: 
        const response = await result.json()
        console.log(response)
        return response
    }
)
const userAuthSlice = createSlice({
    extraReducers: {
        [login.pending]: (state) => {
            state.isLoading = true
        },
        [login.fulfilled]: (state, action) => {
            state.isLoading = false
            state.isAuth = true
        },
        [login.rejected]: (state) => {
            state.isLoading = false
        },
}

server.js

app.post('/login', (req, res) => {
  const email = req.body.email;
  const plainTextPassword = req.body.password;
  User.find({ email: email }).limit(1).exec(function (err, existingUser) {
    if (existingUser.length === 0) {
      res.sendStatus(401)
    } else {
      bcrypt.compare(plainTextPassword, existingUser[0].password, function (err, response) {
        if (response === true) {
          req.session.user = existingUser[0]._id
          res.json(req.session)
        } else {
          res.sendStatus(401)
        }
      })
    }
  }
  )
})

In my loginModal, i console.log the payload from dispatch. My payload is undefined if my promise is rejected from incorrect password. My payload includes the status code if its fulfilled eg correct password. How can i get the status code / payload, even if the promise is rejected? Or is there another approach to this problem?

Solution

You need to check the Response.ok and / or Response.status properties to determine if your request was successful.

If they are not, I would recommend returning a rejected value. The rejected object can have the properties you need like status

const res = await fetch(...);
if (!res.ok) {
  // thunkApi.rejectWithValue
  return rejectWithValue({
    status: res.status,
    message: await res.text(),
  });
}
return res.json();

Then you can check for rejected promises and refer to the status in your consuming code

const handleLogin = async (event) => {
  event.preventDefault();
  try {
    // needs the `.unwrap()` function call
    const result = await dispatch(login({ email, password })).unwrap();
    console.log(result);
  } catch (err) {
    console.warn(err);

    switch (err.status) {
      case 401:
        // do something for 401
        break;
      default:
        // default error handling
    }
  }
}

Answered By – Phil

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published