Hello. I was working on the Passing Thoughts project and I am having issues after implementing the final step (13). I’ve also watched the accompanying video, but the person who recorded it only showed the app deleting the first two thoughts after 15 seconds - my app also does that but the issue lies when trying to add a new thought to the list (which is the whole point of the app). When I hit the submit button with some text in it, it seems that the thought gets added and then immediately deleted afterwards. Consequently, I am unable to add any new thoughts to the list. If I use alert
instead of removeThought
, an alert is displayed every time I add a new thought, which is triggering useEffect
.
Here’s the code:
Thought.js
import React, { useEffect } from "react";
export function Thought(props) {
const { thought, removeThought } = props;
const handleRemoveClick = () => {
removeThought(thought.id);
};
useEffect(() => {
const timeRemaining = thought.expiresAt - Date.now();
const timeout = setTimeout(() => {
removeThought(thought.id);
}, timeRemaining);
return () => {
clearTimeout(timeout);
};
}, [thought]);
return (
<li className="Thought">
<button
aria-label="Remove thought"
className="remove-button"
onClick={handleRemoveClick}
>
×
</button>
<div className="text">{thought.text}</div>
</li>
);
}
AddThought.js
import React, { useState } from "react";
import { generateId, getNewExpirationTime } from "./utilities";
export function AddThoughtForm(props) {
const [text, setText] = useState("");
function handleTextChange(event) {
setText(event.target.value);
}
function handleSubmit(event) {
event.preventDefault();
//create new thought object
if (text.length > 0) {
const thought = {
id: generateId(),
text: text,
expirestAt: getNewExpirationTime(),
};
props.addThought(thought);
setText("");
}
}
return (
<form onSubmit={handleSubmit} className="AddThoughtForm">
<input
onChange={handleTextChange}
value={text}
type="text"
aria-label="What's on your mind?"
placeholder="What's on your mind?"
/>
<input type="submit" value="Add" />
</form>
);
}
App.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { AddThoughtForm } from "./AddThoughtForm";
import { Thought } from "./Thought";
import { generateId, getNewExpirationTime } from "./utilities";
export default function App() {
const [thoughts, setThoughts] = useState([
{
id: generateId(),
text: "This is a place for your passing thoughts.",
expiresAt: getNewExpirationTime(),
},
{
id: generateId(),
text: "They'll be removed after 15 seconds.",
expiresAt: getNewExpirationTime(),
},
]);
function addThought(thought) {
setThoughts((prevThoughts) => [thought, ...prevThoughts]);
}
function removeThought(thoughtId) {
setThoughts((thoughts) => {
return thoughts.filter(thought => thought.id !== thoughtId );
});
}
return (
<div className="App">
<header>
<h1>Passing Thoughts</h1>
</header>
<main>
<AddThoughtForm addThought={addThought} />
<ul className="thoughts">
{thoughts.map((thought) => (
<Thought key={thought.id} thought={thought} removeThought={removeThought} />
))}
</ul>
</main>
</div>
);
}
utilities.js
export function getNewExpirationTime() {
return Date.now() + 15 * 1000;
}
let nextId = 0;
export function generateId() {
const result = nextId;
nextId += 1;
return result;
}