No Time Dad

A blog about web development written by a busy dad

React Interview Questions - Click to Edit Form

Using the code and component below as a starting point, add the ability to edit the user’s first name, last name, and email address. This should happen without a page refresh and the changes should be stored in the component’s state once they’re confirmed by the user.

The user data should be in a “readonly” state until the user clicks on the “Click to Edit” button and enters “editing” mode. While in editing mode, a button should be displayed to allow the user to save their changes. Once the user clicks on the “Click to Save” button, the data should be in a “readonly” state again.

Jump to solution

Starting code
import React, { useState } from "react"

export const UserComponent = () => {
  const [user, setUser] = useState({
    firsName: "Fred",
    lastName: "Jones",
    email: "fred@jones.com",
  })

  return (
    <form>
      <div>
        <label htmlFor="firstName">First Name</label>: {user.firsName}
      </div>
      <div>
        <label htmlFor="lastName">Last Name</label>: {user.lastName}
      </div>
      <div>
        <label htmlFor="email">Email</label>: {user.email}
      </div>
      <button>Click To Edit</button>
    </form>
  )
}
Starting component
: Fred
: Jones
: fred@jones.com

Solution

I really like this React interview question. It’s a great way to see if the candidate has a baseline understanding of React, as well as more advanced concepts. It also mixes in some HTML knowledge, which is a nice bonus.

The button

I’m going to start with the edit button and its state. The button is responsible for toggling between the “editing” and “readonly” states. So, I’ll need to add a new state value to track the editing state. I’ll use React’s useState hook to create the new state value.

Once I have the new state value for the editing mode, I can use React’s conditional rendering to render different buttons based on the editing state. I’m going to use the ternary operator to render the “Click to Edit” button if the user is not in editing mode and the “Click to Save” button if the user is in editing mode.

The updated code looks like this:

export const UserComponent = () => {
  const [user, setUser] = useState({
    firsName: "Fred",
    lastName: "Jones",
    email: "fred@jones.com",
  })
  const [editing, setEditing] = useState(false)

  return (
    <form>
      <div>
        <label htmlFor="firstName">First Name</label>: {user.firsName}
      </div>
      <div>
        <label htmlFor="lastName">Last Name</label>: {user.lastName}
      </div>
      <div>
        <label htmlFor="email">Email</label>: {user.email}
      </div>
      {editing ? (
        <button type="button" onClick={() => setEditing(false)}>
          Click To Save
        </button>
      ) : (
        <button type="button" onClick={() => setEditing(true)}>
          Click to Edit
        </button>
      )}
    </form>
  )
}
: Fred
: Jones
: fred@jones.com
The input fields

Right now, there aren’t any input fields. But, they should be displayed when the user clicks on the “Click to Edit” button and hidden when the user clicks on the “Click to Save” button. To do this I’m going need to use React conditional rendering again to show and hide the inputs via the ternary operator.

When the user clicks on the “Click to Edit” button I want to replace the text with an input field. And vice versa when the user clicks on the “Click to Save” button. Once again, ternary operator for conditional rendering comes to the rescue. But, I also need to patch the state with the new values and map those values to the value attribute of the input fields. This creates what’s known as a React controlled component.

The onChange event handler will update the state with the new value from the input field. The value attribute of the input field will be set to the value from the state. In this example I’m using the JavaScript spread operator to copy the state object and then patch the firsName, lastName, and email properties with the new values.

Fred
Jones
fred@jones.com

Conclusion

Below is the code I’d submit as my solution to this interview question. It’s a bit messy, but it’s a good starting point. It also meets all of the interview question’s requirements. And this is the most important point of any interview question, because it’s not meant to be production quality code but it is meant to check all of the requirement boxes.

It’s important to remember that interviewers want to hear you thinking through a problem, not just seeing the solution. It’s also inevitable that you’ll get stuck and not know the exact answer. And that’s okay. Possibly even expected. The important thing is to keep talking and keep thinking throughout the interview. It’s also a good idea to ask questions if you don’t understand something about the question.

At the end of the day, interviewers want to know that you can not only find solutions to problems, but that you’re not afraid to ask questions when you’re stuck or don’t understand something.

A few more example React interview questions:

Solution

import React, { useState } from "react"

const UserComponent = () => {
  const [user, setUser] = useState({
    firstName: "Fred",
    lastName: "Jones",
    email: "fred@jones.com",
  })
  const [editing, setEditing] = useState(false)

  return (
    <form>
      <div>
        <label htmlFor="firstName">First Name: </label>
        {editing ? (
          <input
            name="firstName"
            onChange={event =>
              setUser({ ...user, firstName: event.target.value })
            }
            value={user.firstName}
          />
        ) : (
          <span>{user.firstName}</span>
        )}
      </div>
      <div>
        <label htmlFor="lastName">Last Name: </label>
        {editing ? (
          <input
            name="lastName"
            onChange={event =>
              setUser({ ...user, lastName: event.target.value })
            }
            value={user.lastName}
          />
        ) : (
          <span>{user.lastName}</span>
        )}
      </div>
      <div>
        <label htmlFor="email">Email: </label>
        {editing ? (
          <input
            name="email"
            onChange={event => setUser({ ...user, email: event.target.value })}
            value={user.email}
          />
        ) : (
          <span>{user.email}</span>
        )}
      </div>
      {editing ? (
        <button type="button" onClick={() => setEditing(false)}>
          Click To Save
        </button>
      ) : (
        <button type="button" onClick={() => setEditing(true)}>
          Click to Edit
        </button>
      )}
    </form>
  )
}
Fred
Jones
fred@jones.com