Skip to content

Commit

Permalink
fix(react/todo-list): persist todo-items across reloads. Fixes #185 (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
proghax333 authored Nov 15, 2023
1 parent 0129106 commit 25e1f4e
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 45 deletions.
23 changes: 11 additions & 12 deletions react/src/machine-coding/todo-list/list.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import styles from "./todo.module.scss";
import styles from './todo.module.scss';

function List({ items, handleEditClick, handleDeleteClick, handleCompleteClick }) {
return items.map((item, idx) => (
<li className={styles.item} key={item.id} title="Double click to mark completed" onDoubleClick={() => handleCompleteClick(item)}>
<span className={item.isDone ? styles.completed: ""}>{item.value}</span>
return items.map((item) => (
<li
className={styles.item}
key={item.id}
title="Double click to mark completed"
onDoubleClick={() => handleCompleteClick(item.id)}
>
<span className={item.isDone ? styles.completed : ''}>{item.value}</span>
<div>
<button
className={styles.editBtn}
onClick={() => handleEditClick(item)}
>
<button className={styles.editBtn} onClick={() => handleEditClick(item)}>
Edit
</button>
<button
className={styles.deleteBtn}
onClick={() => handleDeleteClick(idx)}
>
<button className={styles.deleteBtn} onClick={() => handleDeleteClick(item.id)}>
Delete
</button>
</div>
Expand Down
67 changes: 34 additions & 33 deletions react/src/machine-coding/todo-list/todo.jsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
import React, { useState } from "react";
import List from "./list";
import styles from "./todo.module.scss";
import React, { useEffect, useState } from 'react';
import List from './list';
import styles from './todo.module.scss';

const Todo = () => {
const [value, setValue] = useState("");
const [value, setValue] = useState('');
const [items, setItems] = useState([]);
const [editInfo, setEditInfo] = useState(null);

const isInitialRender = React.useRef(true);

useEffect(() => {
const data = localStorage.getItem('items');
if (data) {
setItems(JSON.parse(data));
}
}, []);

useEffect(() => {
if (isInitialRender.current) {
isInitialRender.current = false;
} else {
localStorage.setItem('items', JSON.stringify(items));
}
}, [items]);

const addItem = (value) => {
setItems((prevItems) => [
...prevItems,
{ value, id: new Date().getTime(), isDone: false }
]);
setItems((prevItems) => [...prevItems, { value, id: new Date().getTime(), isDone: false }]);
};

const updateItem = (newValue) => {
setItems((prevItems) =>
prevItems.map((item) =>
item.id === editInfo.id ? { ...item, value: newValue } : item
)
);
setItems((prevItems) => prevItems.map((item) => (item.id === editInfo.id ? { ...item, value: newValue } : item)));
setEditInfo(null);
};

const handleCompleteClick = (id) => {
setItems((prevItems) =>
prevItems.map((item) =>
item.id === id ? { ...item, isDone: !item.isDone } : item
)
);
setItems((prevItems) => prevItems.map((item) => (item.id === id ? { ...item, isDone: !item.isDone } : item)));
};

const handleEditClick = ({ id, value }) => {
Expand All @@ -38,7 +44,7 @@ const Todo = () => {

const handleDeleteClick = (id) => {
if (editInfo?.id === id) {
setValue("");
setValue('');
setEditInfo(null);
}
setItems((prevItems) => prevItems.filter((item) => item.id !== id));
Expand All @@ -51,35 +57,30 @@ const Todo = () => {
} else {
addItem(value);
}
setValue("");
setValue('');
};

const cancelHandler = () => {
setValue("");
setValue('');
setEditInfo(null);
};

return (
<div className={styles.App}>
<form onSubmit={submitHandler}>
<input
type="text"
value={value}
placeholder="Enter your todo"
onChange={(e) => setValue(e.target.value)}
/>
<input type="text" value={value} placeholder="Enter your todo" onChange={(e) => setValue(e.target.value)} />
<button type="submit" disabled={!value}>
{editInfo ? "Update" : "Submit"}
{editInfo ? 'Update' : 'Submit'}
</button>
<button
type="reset"
onClick={cancelHandler}
disabled={!(value || editInfo)}
>
<button type="reset" onClick={cancelHandler} disabled={!(value || editInfo)}>
Cancel
</button>
</form>

<div className={styles.hint}>
<i>Double click on todo to toggle completion status</i>
</div>

<List
items={items}
handleEditClick={handleEditClick}
Expand Down
6 changes: 6 additions & 0 deletions react/src/machine-coding/todo-list/todo.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
}
}

.hint {
margin: 0.5rem 0;
font-size: 0.9rem;
color: #333;
}

@media screen and (width >= 768px) {
.App {
width: 50%;
Expand Down

0 comments on commit 25e1f4e

Please sign in to comment.