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? 
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. 
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. 
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);