Hey everyone,
I have written a CRUD fullstack tasks app in react. Here is the code so far:
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import './styles/styles.scss';
class App extends React.Component {
constructor() {
super();
this.handleAddTask = this.handleAddTask.bind(this);
this.handleDeleteTask = this.handleDeleteTask.bind(this);
this.handleToggleComplete = this.handleToggleComplete.bind(this);
this.state = {
tasks: []
};
}
getTasks() {
axios.get('http://localhost:3000/tasks')
.then(response => {
this.setState({ tasks: response.data });
})
.catch(function (error) {
console.log(error);
});
}
handleAddTask(e) {
e.preventDefault();
const newTaskDescription = e.target.elements.task.value.trim();
if(newTaskDescription.length) {
axios.post('http://localhost:3000/tasks', {
description: newTaskDescription
}).then(() => {
this.getTasks();
});
e.target.elements.task.value = '';
}
}
handleDeleteTask(e) {
e.preventDefault();
const taskId = e.target.getAttribute('data-id');
axios.delete(`http://localhost:3000/tasks/${taskId}`)
.then(() => {
this.getTasks();
})
.catch(function (error) {
console.log(error);
});
}
handleToggleComplete(e) {
e.preventDefault();
const taskId = e.target.getAttribute('data-id');
const tasks = this.state.tasks;
const taskIndex = tasks.findIndex(task => task._id === taskId);
tasks[taskIndex].completed = !tasks[taskIndex].completed;
this.setState(() => {
return { tasks };
}, () => {
axios.put(`http://localhost:3000/tasks/${taskId}`, { completed: this.state.tasks[taskIndex].completed})
.then(() => {
this.getTasks();
})
.catch(function (error) {
console.log(error);
});
});
}
componentDidMount() {
this.getTasks();
}
render() {
return (
<div>
<h1>Here is a list of Tasks</h1>
<form onSubmit={this.handleAddTask}>
<input type="text" name="task"/>
<button>Add a task</button>
</form>
{this.state.tasks.length === 0 && <p>Please add a task to get started</p>}
<ul>
{
this.state.tasks.map((task) => {
return <li
key={task._id}
className={ task.completed ? 'completed' : '' }
>
{task.description}
<form
data-id={task._id}
onSubmit={this.handleToggleComplete}
>
<button>Toggle</button>
</form>
<form
data-id={task._id}
onSubmit={this.handleDeleteTask}
>
<button>Delete</button>
</form>
</li>;
})
}
</ul>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
Everything is working correctly with the above code. However I am currently trying to refactor it. by splitting it up into components like so.
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import './styles/styles.scss';
class App extends React.Component {
constructor() {
super();
this.handleAddTask = this.handleAddTask.bind(this);
this.handleDeleteTask = this.handleDeleteTask.bind(this);
this.handleToggleComplete = this.handleToggleComplete.bind(this);
this.state = {
tasks: []
};
}
getTasks() {
axios.get('http://localhost:3000/tasks')
.then(response => {
this.setState({ tasks: response.data });
})
.catch(function (error) {
console.log(error);
});
}
handleAddTask(e) {
e.preventDefault();
const newTaskDescription = e.target.elements.task.value.trim();
if(newTaskDescription.length) {
axios.post('http://localhost:3000/tasks', {
description: newTaskDescription
}).then(() => {
this.getTasks();
});
e.target.elements.task.value = '';
}
}
handleDeleteTask(e) {
e.preventDefault();
const taskId = e.target.getAttribute('data-id');
axios.delete(`http://localhost:3000/tasks/${taskId}`)
.then(() => {
this.getTasks();
})
.catch(function (error) {
console.log(error);
});
}
handleToggleComplete(e) {
e.preventDefault();
const taskId = e.target.getAttribute('data-id');
const tasks = this.state.tasks;
const taskIndex = tasks.findIndex(task => task._id === taskId);
tasks[taskIndex].completed = !tasks[taskIndex].completed;
this.setState(() => {
return { tasks };
}, () => {
axios.put(`http://localhost:3000/tasks/${taskId}`, { completed: this.state.tasks[taskIndex].completed})
.then(() => {
this.getTasks();
})
.catch(function (error) {
console.log(error);
});
});
}
componentDidMount() {
this.getTasks();
}
render() {
return (
<div>
<h1>Here is a list of Tasks</h1>
<form onSubmit={this.handleAddTask}>
<input type="text" name="task"/>
<button>Add a task</button>
</form>
{this.state.tasks.length === 0 && <p>Please add a task to get started</p>}
<ul>
{
this.state.tasks.map((task) => {
return <Task
id={task._id}
key={task._id}
className={task.completed ? 'completed' : ''}
description={task.description}
handleDeleteTask={this.handleDeleteTask}
handleToggleComplete={this.handleToggleComplete}
/>;
})
}
</ul>
</div>
);
}
}
const Task = (props) => {
return (
<div>
{props.description}
<form
data-id={props._id}
onSubmit={props.handleToggleComplete}
>
<button>Toggle</button>
</form>
<form
data-id={props._id}
onSubmit={ props.handleDeleteTask}
>
<button>Delete</button>
</form>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('app'));
And here’s what the data in the API looks like:
0: {completed: false, _id: "5d4eeb8c8925d7368654559d", description: "skaksjakjjsa", __v: 0}
1: {completed: true, _id: "5d4eeb968925d7368654559f", description: "abcdefghijklmnop", __v: 0}
2: {completed: true, _id: "5d4f0de930952a4064afa954", description: "akjkjskjaka", __v: 0}
3: {completed: false, _id: "5d4f10ae2faf70425804a3c4", description: "sasas", __v: 0}
4: {completed: false, _id: "5d4f10b22faf70425804a3c5", description: "ksksksksk", __v: 0}
5: {completed: false, _id: "5d4f10b62faf70425804a3c6", description: "dgdgdgdgdg", __v: 0}
6: {completed: false, _id: "5d4f12792faf70425804a3c7", description: "alallalal", __v: 0}
7: {completed: false, _id: "5d4f12822faf70425804a3c8", description: "abcdefghijklmnop", __v: 0}
However now that I have spit it up and attempted to pass down the handleDeleteTask and handleToggleComplete tasks as props it is telling me that e.target.getAttribute(‘data-id’) is not defined?
Can anyone see the mistake here?
Thanks!