React Coding Challenge Interview

Hey Everyone!

I was recently sent a set of interview questions from a company to answer in a very short time frame. It has come and passed and now I am working through the problems so I can be a little more prepared in the future. This questions has been a problem for me, and I am lost on what I should be doing with it.

Basically I have a react app (they wanted it all in one file, so no separate files were allowed). They wanted me to create a todo list, been there, done that. The issue is after the item is added. They want me to apply a css class (text-decoration: line-through) when the item is clicked to show that it has been completed. But they they also want to be able to uncheck, so it would need to be able to toggle.

What they gave me was this for the css:

<style>{`
.is-done {
text-decoration: line-through
}
`}</style>

So I need to apply this class on the individual li’s when the item is clicked. My code is below, how would I accomplish this? Any help would be appreciated!

import React, { Component } from "react";
import "./App.css";

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      input: "",
      list: [],
      count: 0,
      active: true
    };
  }

  handleChange = event => {
    this.setState({
      input: event.target.value
    });
  };

  onSubmit = event => {
    event.preventDefault();
    event.target.reset();
    this.setState({
      input: "",
      list: [...this.state.list, this.state.input]
    });
  };

  strike = () => {
    this.setState({
      active: !this.state.active
    });
  };

  render() {
    return (
      <div className="todo-list">
        <h1>Task List</h1>
        <form onSubmit={this.onSubmit}>
          <input
            type="text"
            value={this.state.item}
            onChange={this.handleChange}
          />
          <button type="submit" value="Submit">
            Add
          </button>
        </form>
        <p>0 remaining out of {this.state.list.length}</p>
        <ul>
          {this.state.list.map((item, index) => (
            <li onClick={this.strike} key={index}>
              {item}
            </li>
          ))}
        </ul>
        <style>{`
          .is-done {
              text-decoration: line-through
          }
            `}</style>
      </div>
    );
  }
}

export default App;

I would add and remove the .is-done class from the li depending on the completed state of the particular item.

<li className={item.completed && 'is-done'}>

For that you’ll have to save the completed state for each item in the list as at the moment you only have an array of strings (as far as I saw). You need to create an array of objects like:

{ text: 'My to do text', completed: false }

Then, when you click the li you should pass the id or the index (as it is easier in your case) of the particular to-do item from the array. And in the strike method, you’ll update the corresponding to-do based on the index provided.

2 Likes

So I kind of get this and I kind of don’t… I guess this is where I am having issues in React right now.

Well… I am open to answer your questions. What part is confusing? :slight_smile:

So what your saying is that I need to change my state from just array:[] to bring in an object that contains the list item as well as the completed already set to false. I think I kind of get it. Let me give it a try real quick.

Make sure you try first before reading, you might get spoiled. :laughing:

Yes, so basically now you only save the text in a string format.

What you’ll need to do is to have an array of objects, and beside the text, you should save the completed boolean. It will look like this:

list: [{
  text: 'My first to do',
  completed: false
}, {
  text: 'Another to do',
  completed: false
}]

And also, when you save a new todo, instead of saving just the input, you save the completed value too, and set it by default to false, as all the todo items are incompleted first.

Then, when you click on the li, you’ll have to pass the index of the corresponding item you are clicking for that you can call the this.strike function with an argument, something like this:

<li onClick={() => this.strike(index)} key={index} />

And in the strike function you’ll have to find that item in the array (you have the index and it’s easy to do so with the array’s .filter() function) and just change the completed flag. :slight_smile:

Hope this is helpful.

AHHHHHHHH. I just keep breaking it! lol

So when I am doing handle change is this when I create this object? or is that part of the inSubmit. I keep getting all kinds of errors… Feeling pretty down on this.

Well, when you submit you should add the new object to the array. Until then you’ll update the this.state.input value which you’ll use to add the text prop in your object.

Well, when your submit you should add new object into an array with {name: 'text , done: false} by default will false.

pass item as an argument to strick method to identify the item . and filter item in existing list . then change done to true,

check bellow code.

import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./App.css";

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      input: "",
      list: [],
      count: 0,
      active: true
    };
  }

  handleChange = event => {
    this.setState({
      input: event.target.value
    });
  };

  onSubmit = event => {
    event.preventDefault();
    event.target.reset();
    this.setState(prevState => ({
      input: "",
      list: [
        ...prevState.list,
        {
          name: this.state.input,
          done: false
        }
      ]
    }));
 
  };

  strike = item => {
    console.log(item);
    const completedList = this.state.list.find(list => list.name === item.name);
    completedList.done = !completedList.done;
    this.setState(prevState => ({
      list: prevState.list
    }));
  };

  render() {
    const completedList = this.state.list.filter(list => list.done === true);
    return (
      <div className="todo-list">
        <h1>Task List</h1>
        <form onSubmit={this.onSubmit}>
          <input
            type="text"
            value={this.state.item}
            onChange={this.handleChange}
          />
          <button type="submit" value="Submit">
            Add
          </button>
        </form>
        <p>
          {this.state.list.length - completedList.length} remaining out of{" "}
          {this.state.list.length}
        </p>
        <ul>
          {this.state.list.map((item, index) => (
            <li
              onClick={() => this.strike(item)}
              key={index}
              className={item.done ? "is-done" : ""}
            >
              {item.name}
            </li>
          ))}
        </ul>
        <style>{`
          .is-done {
              text-decoration: line-through
          }
            `}</style>
      </div>
    );
  }
}

document.body.innerHTML = "<div id='root'></div>";
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);