I’m new to React. I have a backend api. When the user is on the "Login Page" and enters a wrong username or password, after submitting the form, the api returns a message "Invalid username/password.".
I added this:
const [errors, setErrors] = useState(null)
And then in my try/catch block:
catch (error) {
if (error.response.status === 401) {
setErrors(error.response.data.message)
console.log(errors)
} else {
console.log("There was a problem or the request was cancelled.")
}
}
After a few seconds, I see the message saved in state (see image).
I’m trying to retrieve it in my jsx using <div>{ errors !== null ? errors : '' }</div>
but I have 2 issues. 1) I get a runtime error:
Objects are not valid as a React child (found: object with keys {}). If you meant to render a collection of children, use an array instead.
- Even if I manage to get around this, the
console.log(errors)
returns undefined the first time I submit the form, when I submit it the second time or more, I see the message in the console.
How can I save error messages in state, and retrieve them easily?
3
Answers
I was using Formik and Yup for Form Validation, as it turns out Formik uses
errors, setErrors
already for state, so mine was conflicting. After changing mineto apiErrors, setApiErrors
with the samesetApiErrors(error.response.data.message)
and using{<div>{ apiErrors }</div>}
in the jsx, the validation message appears. Thank you to all who answered!The error indicates that your state is holding
error.response.data.message
, which happens to be an object. You will need to convert this to a string to be displayed in the jsx<div>
element.To do that, you could store it as a string from the get-go in your state like:
setErrors(JSON.stringify(error.response.data.message))
The code:
will never show you the "new value" of
errors
because the "set state function" is asynchronous so it will update the value of its state variable "at some point in the future" (after the current render completes) and that function will schedule the component for a re-render, but you will not see the new value until that subsequent render.As @TP95 mentions, it looks like the value you are getting is an object rather than a string. You could either render a field from the object, or you could convert to entire object to a string with
JSON.stringify(errors)
, or something along those lines.