DEV Community

Cover image for React Live Code Challenge...What I learned
Meks (they/them)
Meks (they/them)

Posted on

React Live Code Challenge...What I learned

I'm in the midst of my job search looking for a software engineering position after completing Flatiron's Bootcamp. Last week I had an hour-long interview with a company I really liked and I got great vibes from my interviewer and we had a fascinating conversation. We spent 20 minutes discussing my experience and what the company does, followed by about half an hour of a live code challenge with react, with some time for me to ask questions at the end.

I was successful in completing the challenge and felt pretty darn proud of myself. When I got the notice that I would not be moving on to the next round I was bummed out, to say the least. But I asked my interviewer for feedback and I'm really glad I did! Culturally I was a great fit, but he had a lot of candidates and they needed to analyze who would be the best fit at the time for their needs. He gave me valuable insight into how I approached the live code and I wanted to share both as a way for me to reflect on the experience, and to help others also doing react interviews!

The challenge was to be able to click between two different tabs to show two different images. And to do this twice for two different customers. We worked in codesandbox.io to complete the challenge. I'm recreating it on my local machine for my own personal practice and so others can follow along if they wish.

I was given an app component:
src/App.js

import './App.css';
import Dashboard from './Dashboard';

function App() {
  return (
    <div className="App">
      <Dashboard />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

with simple styling:
src/App.css

.App {
  text-align: center;
}
Enter fullscreen mode Exit fullscreen mode

And the dashboard component contained:
src/Dashboard.js

import React from 'react'

import customer1Events from "./fake-charts/events-1.png";
// import customer1Performance from "./fake-charts/perf-1.png";
import customer2Ftp from "./fake-charts/ftp-2.png";
// import customer2Performance from "./fake-charts/perf-2.png";

import "./styles.css";

const Dashboard = () => {
  return (
    <div>
      {/* Placeholder, feel free to edit the structure below */}
      <div className="box">
        <h1>Customer 1</h1>

        <div className="tabs">
          <div className="tab selected">
            Search events
          </div>
          <div className="tab">
            Performance
          </div>
        </div>

        <div>
            <img src={customer1Events} alt="Search events over time" />
        </div>
      </div>

      <div className="box">
        <h1>Customer 2</h1>

        <div className="tabs">
          <div className="tab selected">
            FTP Usage
          </div>
          <div className="tab">
            Performance
          </div>
        </div>

        <div>
            <img src={customer2Ftp} alt="FTP usage" />
        </div>
      </div>
    </div>
  )
}

export default Dashboard
Enter fullscreen mode Exit fullscreen mode

and was provided the styling:
src/styles.css

.tabs {
  display: flex;
}

.tab {
  padding: 10px;
  cursor: pointer;
}

.tab.selected {
  background-color: darkseagreen;
}

.box {
  padding: 1em;
  border: 1px solid gray;
  border-radius: 2px;
}

.box + .box {
  margin-top: 1em;
}
Enter fullscreen mode Exit fullscreen mode

And the images provided were in a fake-charts folder in the src folder.
The result looked like this in the browser:
Alt Text

In hindsight and even at the time it didn't seem all that difficult, but I think I really let my nerves get the best of me. I made two mistakes off the bat, one is that the provided code included the imports for the two images I was going to need, and it was commented out directly below the ones in use. My brain didn't even register them and I wrote practically the same line beneath them. The other mistake was that after I was successfully toggling back and forth between the images my interviewer had to remind me that they were expecting the backgrounds of the tabs to change when clicked too, and I had to go back and add that in. Both of these were reflected in the feedback given; "I think taking a bit more time to analyze the behavior and the code given would've been useful. Specifically, I'm thinking about missing the UI change that had to happen when clicking the different tabs, or (way less importantly) missing that there were imports commented out with the extra images for you to use. I do agree that live coding in front of someone in the context of an interview is far from stress-free so I understand that some things might have been missed."

So yes, I'm annoyed with myself that I missed such simple things. But the biggest red flag was how I passed information to the on-click handler to update which image had been selected. I originally wrote four separate functions for each onClick, and I even stated aloud that I know it was redundant but I wanted to get it working, and then would be able to refactor to make the code drier.

I decided to use the React Hook useState to keep track of which image to display and then I added an onClickHandler for both tabs for customer 1 which would update the state with the name of the image to be displayed and used a ternary in the JSX to determine which image would be shown.

import React, { useState } from 'react'

import customer1Events from "./fake-charts/events-1.png";
import customer1Performance from "./fake-charts/perf-1.png";
import customer2Ftp from "./fake-charts/ftp-2.png";
// import customer2Performance from "./fake-charts/perf-2.png";

import "./styles.css";

const Dashboard = () => {

  const [customer1, setCustomer1] = useState('customer1Events')

  const onClickHandler = () => {
    setCustomer1('customer1Events')
  }

  const onClickHandler2 = () => {
    setCustomer1('customer1Performance')
  }

  return (
    <div>
      {/* Placeholder, feel free to edit the structure below */}
      <div className="box">
        <h1>Customer 1</h1>

        <div className="tabs">
          <div className="tab selected" onClick={ onClickHandler }>
            Search events
          </div>
          <div className="tab" onClick={ onClickHandler2 }>
            Performance
          </div>
        </div>

        <div>
          { customer1 === 'customer1Events' ?
            <img src={customer1Events} alt="Search events over time" />
            :
            <img src={customer1Performance} alt="Performance over time" />
          }
        </div>
      </div>
...
    </div>
  )
}

export default Dashboard

Enter fullscreen mode Exit fullscreen mode

I repeated the logic for customer two and could see that clicked on the tabs would update and show the correct image. This was when my interviewer pointed out that I needed to change the color of the tabs as well. Since I was using state to keep track of the image, I was able to reuse it and added in a ternary that would change the className of the div from tab to tab selected.

     <div className="tabs">
          <div className={ customer1 === 'customer1Events' ? "tab selected" : "tab"} onClick={ onClickHandler }>
            Search events
          </div>
          <div className={ customer1 === 'customer1Performance' ? "tab selected" : "tab"} onClick={ onClickHandler2 }>
            Performance
          </div>
        </div>
Enter fullscreen mode Exit fullscreen mode

I also did this for customer 2, and at this point, I could toggle between the two tabs and show the correct CSS:

Alt Text

So at this point, I had it functioning, and my interviewer asked me to refactor so that I was using one onClick function for customer one. This was a perfectly reasonable thing to ask and I had even anticipated it, but this is where I hit a snag and had that red flag issue. And I know exactly why my brain went the way it did. I knew that with forms you can access an input's attributes using e.target.name or e.target.value, and my brain spun out the thought, "Yeah! That'll work for a div!" Except it doesn't. While I was struggling with e.target.name returning undefined my interviewer pointed out that using the dot notation on a custom attribute wouldn't work in React and said there might be a function to get a specific attribute. So I did a quick google and found exactly what I needed: e.target.getAttribute('name'). I implemented this to determine which image to display.

  const onClickHandler = (e) => {
    e.target.getAttribute('name') === 'customer1Events' ?
    setCustomer1('customer1Events')
    :
    setCustomer1('customer1Performance')
  }

...

 <div className="tabs">
          <div name="customer1Events" className={ customer1 === 'customer1Events' ? "tab selected" : "tab"} onClick={ (e) => onClickHandler(e) }>
            Search events
          </div>
          <div className={ customer1 === 'customer1Performance' ? "tab selected" : "tab"} onClick={ (e) => onClickHandler(e) }>
            Performance
          </div>
        </div>
Enter fullscreen mode Exit fullscreen mode

And while this does work, in my feedback my interviewer pointed out that typically in React we don't want to attach information to the DOM which is what I did by giving the div a name. A better way would have been to take advantage of inline functions to pass arbitrary data around, like in this first example. This also would have helped with another thing I missed, I didn't give a name to the other div. It didn't matter for this particular coding challenge but it would have created an issue if we had wanted to add more tabs. By passing the name explicitly to the click handler it's more likely that I would have noticed that I didn't give the other div a name.

This was really an 'a ha!' moment for me and it helped me settle this weird feeling I had about writing the getAttribute method, something I'd done before when working with vanilla javascript but not in React. Now I have a clear path forward for how I would better refactor this! Based on that information I have since refactored it to look like this:

  const onClickHandler = (selection) => {
   selection === 'customer1Events' ?
    setCustomer1('customer1Events')
    :
    setCustomer1('customer1Performance')
  }
...
  <div className="box">
        <h1>Customer 1</h1>

        <div className="tabs">
          <div className={ customer1 === 'customer1Events' ? "tab selected" : "tab"} onClick={ () => onClickHandler('customer1Events') }>
            Search events
          </div>
          <div className={ customer1 === 'customer1Performance' ? "tab selected" : "tab"} onClick={ () => onClickHandler('customer1Performance') }>
            Performance
          </div>
        </div>

        <div>
          { customer1 === 'customer1Events' ?
            <img src={customer1Events} alt="Search events over time" />
            :
            <img src={customer1Performance} alt="Performance over time" />
          }
        </div>
      </div>
Enter fullscreen mode Exit fullscreen mode

Once this was all working, I decided to change the ternary for the onClickHandler to a switch case so that I could reuse it for customer 2. With all those refactors and including the code for customer 2 this is what I have ended up with:

import React, { useState } from 'react'

import customer1Events from "./fake-charts/events-1.png";
import customer1Performance from "./fake-charts/perf-1.png";
import customer2Ftp from "./fake-charts/ftp-2.png";
import customer2Performance from "./fake-charts/perf-2.png";

import "./styles.css";

const Dashboard = () => {

  const [customer1, setCustomer1] = useState('customer1Events')
  const [customer2, setCustomer2] = useState('customer2FTP')

  const onClickHandler = (selection) => {
    switch(selection) {
      case 'customer1Events':
        setCustomer1('customer1Events')
        break;
      case 'customer1Performance':
        setCustomer1('customer1Performance')
        break;
      case 'customer2FTP':
        setCustomer2('customer2FTP')
        break;
      case 'customer2Performance':
        setCustomer2('customer2Performance')
        break;
      default:
        setCustomer1('customer1Events')
        setCustomer2('customer2FTP')
    }
  }

  return (
    <div>
      {/* Placeholder, feel free to edit the structure below */}
      <div className="box">
        <h1>Customer 1</h1>

        <div className="tabs">
          <div className={ customer1 === 'customer1Events' ? "tab selected" : "tab"} onClick={ () => onClickHandler('customer1Events') }>
            Search events
          </div>
          <div className={ customer1 === 'customer1Performance' ? "tab selected" : "tab"} onClick={ () => onClickHandler('customer1Performance') }>
            Performance
          </div>
        </div>

        <div>
          { customer1 === 'customer1Events' ?
            <img src={customer1Events} alt="Search events over time" />
            :
            <img src={customer1Performance} alt="Performance over time" />
          }
        </div>
      </div>

      <div className="box">
        <h1>Customer 2</h1>

        <div className="tabs">
          <div className={ customer2 === 'customer2FTP' ? "tab selected" : "tab"} onClick={ () => onClickHandler('customer2FTP') }>
            FTP Usage
          </div>
          <div className={ customer2 === 'customer2Performance' ? "tab selected" : "tab"} onClick={ () => onClickHandler('customer2Performance') }>
            Performance
          </div>
        </div>

        <div>
          { customer2 === 'customer2FTP' ?
            <img src={customer2Ftp} alt="FTP usage" />
            :
            <img src={customer2Performance} alt="FTP usage" />
          }
        </div>
      </div>
    </div>
  )
}

export default Dashboard
Enter fullscreen mode Exit fullscreen mode

Now with this setup, it's relatively easy to add more tabs and more customers. The last thing I can think of that I would change is that I personally don't like relying on strings so much, because if I mistype them, I wouldn't get an error associated with the fact that the code wasn't behaving as expected. Instead, I'd want to set some consts that held those strings and pass the consts from the click handler to the switch statement.

If you want to check out the Github repo you can do so here.

Some of my biggest takeaways from this experience include slowing down and really planning out my steps is an important part of the process when coding. Make sure I fully understand the entire problem and what they are asking me to do so I don't miss part of the assignment. And finally, have confidence! I can do all of these things, but I need to let my brain have room to breathe to make sure the adrenaline and stress aren't interfering with my neurons firing. Hope this helps others as well!

Happy Coding!

Top comments (6)

Collapse
 
techdecoderjonny profile image
Jonny Pabon

Great information!

Collapse
 
mmcclure11 profile image
Meks (they/them)

Thanks, Jonny! It was a little painful but a really good learning opportunity!

Collapse
 
techdecoderjonny profile image
Jonny Pabon

The painful ones IMO are the ones your remember the most lol

Thread Thread
 
mmcclure11 profile image
Meks (they/them)

Brains sure are strange that way, certainly seems to be the case for me too!

Collapse
 
tolentinoel profile image
Ellaine Tolentino

Thank you for sharing your live coding experience! I appreciate you taking the time to be in detail.

Collapse
 
mmcclure11 profile image
Meks (they/them)

You're welcome! I'm glad that you've found it useful!