Display Backend Errors to the Frontend
Tags: react, rails, beginners, tutorial
Published: 2023-03-17 03:28:25

Errors are awesome. Errors tell you that something needs to be fixed. If one would not have the error, it would be very frustrating as things would not work and we would not know why. The more specific an error is, the more helpful it is. The best errors are the ones that tell you what is wrong and what you can do to fix it.

When users sign up for an account, or fill out a form on an app, there are (hopefully) validations being checked before a new instance is added to the database. If the data being submitted is not valid, the best case scenario would be for a very specific error message to show up on the screen and direct the user in what to do to submit their information correctly. In this post we will describe how to grab an error from a rails backend and conditionally display it on a react frontend.

Let's get started!

## 1. Validations in the Model

For each model that you create, you can specify what validations are necessary. To do this you would use [Active Record validation methods](https://guides.rubyonrails.org/active_record_validations.html). 

In the example below, a user signs up for an account and creates a new user instance. These validations check that

- there is a username

- the username is unique

- there is a password

- there is an email address

- the email address fits the criteria of a valid email address

```
class User < ApplicationRecord
    validates :name, uniqueness: true
    validates :password, presence: true
    validates :email, presence: true, format: /\w+@\w+\.{1}[a-zA-Z]{2,}/
end
```
If any of these requirements are not met, the user will not be able to sign up. At the same time an error is being generated based on these validations. Now, how will the user see the error and know where they went wrong?

## 2. Controller Error Handling

The next step takes place in the controller. In the User Controller, there is a create method that handles adding a new user. 

```
  def create
        user = User.create!(user_params)
        session[:user_id] = user.id
        render json: user, status: :created
    rescue ActiveRecord::RecordInvalid => e
        render json: { errors: e.record.errors.full_messages }, status: :unprocessable_entity
    end
```
In this case, it is necessary to use the .create! method, as the bang operator (!) will throw an error if saving fails due to the data not passing the validations. If that is the case, we will render a json object that displays an array of error messages. 

```
{
    "errors": [
        "Name has already been taken",
        "Email is invalid"
    ]
}
```

## 3. Save the Error to React State on the Frontend

Now is when we can finally send the error to the frontend. The best way to capture the value of the error is to save it to state. State should initially be set as false, as no errors actually exist on the page load.

`    const [errors, setErrors] = useState(false)
`
Then comes the submit form function. Within the submit is a post request to the backend, sending the new user object to be validated. 

```
function handleSubmit(e) {
        e.preventDefault()
        const user = {
            name,
            password,
            passwordConfirmation,
            email
        }
        fetch('/signup', {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify(user)
    })
    .then((r) => {
        if(!r.ok) {
            return r.json().then((e) => setErrors(Object.values(e).toString()))
        } else {
            return r.json().then((data) => dispatch(signupUser(data)))
        }
    })
}
```
We need two different ways to handle the response, based on wether or not the post request was successful. If the information was successfully saved, then the user information is sent to my redux store to be processed. If not, we need to set the errors in state to the error values of the json object. I converted the array into a string so it would not have to be mapped before displaying.

## 4. Display the Error

Finally! The error is saved in a string format in state. Now all that is needed to display the error to the user is a simple ternary expression. If there is an error, display the error. If not, don't. 

```
{ errors ? <h5 class="text-danger">{errors}</h5> : null }
```