Goodmorning,
it’s more time that not write, i spent some time to study ReactJS, so i think that Angular is better, but so ReactJS has its “why”.
Today i want to show how create a simple React TodoList Example in which i have implemented a system to delete an item, but whit a “undo” (possibilities of recovery the deleted item), the undo has a timer (like gmail) to recover the deleted item.
So Let’s start!
Structure of our Component
We must to think as “React”, so we define our component composition:
– TodoList
— TodoListForm
— TodoListElement
— TodoListElementDelete
At first we must to create the class, and define it in src/components/TodoList.js
Attach all the code below, you can find the entire example on CodeSandBox
import React from "react";
import Header from "./Header";
class TodoListElementDelete extends React.Component {
constructor(props) {
super(props);
this.state = {
index: 0,
timer: 0,
_timeoutRef: null
};
this.onClickUndoDelete = this.onClickUndoDelete.bind(this);
}
componentDidMount() {
this.setState({
index: this.props.index,
timer: this.props.timer
});
}
componentDidUpdate() {
if (this.props.enable) {
this.state._timeoutRef = setTimeout(() => {
if (this.state.timer > 0) {
this.setState({
timer: this.state.timer - 1
});
} else {
this.props.onEndTimerAction();
}
}, 1000);
}
}
componentWillUnmount() {
console.log("componentWillUnmount");
clearTimeout(this.state._timeoutRef);
}
onClickUndoDelete() {
clearTimeout(this.state._timeoutRef);
this.setState({
timer: this.props.timer
});
this.props.onClickUndoDelete();
}
render() {
let classHideItem = this.props.enable ? "" : "hidden";
return (
<div className={"alert alert-danger " + classHideItem}>
You want to undo the action? {this.state.timer}
<button
type="button"
className="btn btn-warning"
onClick={this.onClickUndoDelete}
>
Undo
</button>
</div>
);
}
}
class TodoListElement extends React.Component {
constructor(props) {
super(props);
this.state = {
isDeleted: this.props.item.isDeleted
};
this.onClickDelete = this.onClickDelete.bind(this);
this.onClickUndoDelete = this.onClickUndoDelete.bind(this);
this.onClickPermanentDelete = this.onClickPermanentDelete.bind(this);
this.onClickComplete = this.onClickComplete.bind(this);
}
onClickDelete() {
let index = parseInt(this.props.item.index);
this.props.removeItem(index);
}
onClickUndoDelete() {
let item = this.props.item;
this.props.undoRemoveItem(item);
}
onClickPermanentDelete() {
this.setState({
isDeleted: true
});
//this.props.definitiveRemoveItem(index);
}
onClickComplete() {
let index = parseInt(this.props.item.index);
this.props.completeItem(index);
}
render() {
let isCompletedClass = this.props.item.isCompleted
? "list-group-item-success"
: "";
const btnActionComplete = this.props.item.isCompleted ? (
""
) : (
<button
type="button"
className="btn btn-success btn-sm"
onClick={this.onClickComplete}
>
Complete
</button>
);
const btnActionDelete = (
<button
type="button"
className="btn btn-danger btn-sm"
onClick={this.onClickDelete}
>
Delete
</button>
);
isCompletedClass = this.state.isDeleted ? "hidden" : isCompletedClass;
return (
<li className={"list-group-item " + isCompletedClass}>
<div className="clarfix">
{this.props.item.value}
<span className="float-right">
{btnActionComplete}
{btnActionDelete}
</span>
</div>
<TodoListElementDelete
index={this.props.item.index}
timer={this.props.timer}
enable={this.props.item.isBeingDeleted}
onClickUndoDelete={this.onClickUndoDelete}
onEndTimerAction={this.onClickPermanentDelete}
/>
</li>
);
}
}
class TodoListForm extends React.Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit(event) {
event.preventDefault();
var newItemValue = this.refs.itemName.value;
if (newItemValue) {
this.props.addItem({ newItemValue });
this.refs.form.reset();
}
}
render() {
return (
<form ref="form" onSubmit={this.onSubmit} className="form-inline">
<div className="input-group mb-3">
<input
type="text"
className="form-control"
ref="itemName"
placeholder="Write todo item"
/>
<div className="input-group-append">
<button className="btn btn-success" type="submit">
Add
</button>
</div>
</div>
</form>
);
}
}
export default class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = {
_lastIndex: 0,
todoItems: [],
undoRemoveItems: [],
timer: 10
};
this.addItem = this.addItem.bind(this);
this.removeItem = this.removeItem.bind(this);
this.undoRemoveItem = this.undoRemoveItem.bind(this);
this.definitiveRemoveItem = this.definitiveRemoveItem.bind(this);
this.completeItem = this.completeItem.bind(this);
}
getNewIndex() {
return this.state._lastIndex + 1;
}
addItem(todoItem) {
const newTodoItem = {
index: this.getNewIndex(),
value: todoItem.newItemValue,
isBeingDeleted: false,
isDeleted: false,
isCompleted: false
};
this.setState({
todoItems: [...this.state.todoItems, newTodoItem],
_lastIndex: newTodoItem.index
});
}
removeItem(itemIndex) {
let itemToBeDeleted = this.state.todoItems.find(x => x.index === itemIndex);
if (itemToBeDeleted) {
itemToBeDeleted.isBeingDeleted = true;
}
this.setState({ todoItems: this.state.todoItems });
}
definitiveRemoveItem(itemIndex) {
console.log("definitiveRemoveItem", itemIndex);
let todoItems = this.state.todoItems;
let undoTodoItem = this.state.undoRemoveItems;
let itemToBeDeleted = todoItems.find(
x => x.index === itemIndex && x.isBeingDeleted
);
let itemInUndo = undoTodoItem.find(x => x.index === itemIndex);
if (itemToBeDeleted && itemInUndo == null) {
todoItems = todoItems.filter(x => x.index !== itemIndex);
} else {
undoTodoItem = undoTodoItem.filter(x => x.index !== itemIndex);
}
this.setState({
todoItems: todoItems,
undoRemoveItems: undoTodoItem
});
}
undoRemoveItem(item) {
let todoItems = this.state.todoItems;
let itemToBeDeleted = todoItems.find(x => x.index === item.index);
itemToBeDeleted.isBeingDeleted = false;
this.setState({
todoItems: todoItems
});
}
completeItem(itemIndex) {
let todoItems = this.state.todoItems;
let itemComplete = todoItems.find(x => x.index === itemIndex);
itemComplete.isCompleted = true;
this.setState({
todoItems: todoItems
});
}
render() {
let items = this.state.todoItems.map((item, index) => {
return (
<TodoListElement
key={index}
item={item}
timer={this.state.timer}
completeItem={this.completeItem}
removeItem={this.removeItem}
undoRemoveItem={this.undoRemoveItem}
definitiveRemoveItem={this.definitiveRemoveItem}
/>
);
});
return (
<div>
<Header />
<div className="container">
<TodoListForm addItem={this.addItem} />
<ul className="list-group"> {items} </ul>
</div>
</div>
);
}
}
Do you have some suggestion about React programming? Thank you!
I used your code to see how it works but it is showing the login page. when I tried to login it showed a alert message to wrong username and password. so I tried to register then went for login. but some error occured. this is message I got. 10 |
11 | addUser(name, password) {
12 | let newUser = { name: name, password: password };
> 13 | let listOfUser = JSON.parse(localStorage.get(“listOfUser”));
| ^ 14 | listOfUser = […listOfUser, newUser];
15 | localStorage.setItem(“listOfUser”, JSON.stringify(listOfUser));
16 | }
View compiled
Register.handleModalConfirm
C:/Users/hbkes/OneDrive/Desktop/personal/front_end_web_development/Module12/loginform/src/components/Register.js:95
92 | };
93 |
94 | handleModalConfirm = () => {
> 95 | AuthUser.addUser(this.state.name, this.state.password);
| ^ 96 | this.handleModalClose();
97 | //this.props.history.push(“/”);
98 | };