Since the argument to the callback-function for setThoughts represents the old state (which is an array) you want to use the spread operator (…) on that same argument. You could change function body to:
There are a few issues in your handleSubmit function in AddThoughtForm. There is a comma after the thought object (use a semi-colon) and you are not accessing the addThought-prop. Here is my handleSubmit:
When you call addThought(thought) you can change that to props.addThought(thought). Basically access it like you would using class components but without using this keyword. The other option to access props seems to be like what was done in thought.js:
const { thought, removeThought } = props;
Also, look over your addThought function in App. Currently, Your new thought argument to addThought function is named the same as the call-back-argument to setThoughts (which represents all the current thoughts). I think the hint was a little misleading in the exercise on this one. You need to make sure to use the (…) spread syntax on the current thoughts.
Here is my full code if you want to look at it: Passing Thoughts
Hello, i need some help find what might be causing my app not to work, i compared my code with some of the codes here on the forum but still not sure why my app is not working at all.
@glennlaw Thank you, it worked perfect! The only thing i am still checking is why niether the thoughts delete after 15 second or i cant delete them when clicked the bottom
In your form, you have onSubmit in two places. First under the tag (which is where it should be). But then you also have it under the input field. In the input field you should not have an onSubmit but only your onChange handler (which you have) and link that to your handleTextChange function. However, I don’t think that is the main problem. You are also importing this:
import { Thought } from './Thought';
But your file is called Thoughts.js with an s on the end. So try to change name of the file to Thought.js so the import matches. If that doesn’t work one option would be to use create-react-app and copy over the code into a local project. It would be easier to find import errors and such using VS-Code for some of these more involved React projects. I ended up doing that for this project and it is also good practice setting up local project.
It should have been Thought.js, I just messed up the description lol.
But yeah, I made the changes and it’s still not working.
Somewhere I had to have skipped something or made a fault.
I wish Codecademy had a video walkthrough on this one, as I’m used to React, but React hooks are still a bit confusing for me.
Hey Andre! Since you’ve figured out the props passing thing, I think I’m having an issue on that! I don’t know if it’s that or if importing/exporting things wrong. I can’t figure what! I think that I’ve done the same thing as you, but you could check on the changes you’ve made? I’ve noticed that on this case, you have called addThought and removeThought with prefixed by props. // is that correct? I’m still unable to add or remove thoughts.
Apps.js
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { AddThoughtForm } from './AddThoughtForm';
import { Thought } from './Thought';
import { generateId, getNewExpirationTime } from './utilities';
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(),
},
]);
const addThought = (thought) => {
setThoughts((thought) => [thought, ...thoughts])
}
const removeThought = (thoughtIdToRemove) => {
setThoughts(thoughts){
thoughts.filter((t)=>!t.id !==thoughtIdToRemove)
}
}
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>
);
}
ReactDOM.render(<App />, document.getElementById('app'));
AppThoughtForm.js
import React, {useState} from 'react';
import { generateId, getNewExpirationTime } from './utilities';
export function AddThoughtForm(props) {
const [text, setText] = useState('')
const handleTextChange=(e)=>{
setText(e.target.value);
}
const handleSubmit=(e)=>{
e.preventDefault();
const thought = {id: generateId(),
text: text,
expiresAt: getNewExpirationTime()}
if (text.length > 0){
addThought(thought)
}
setText('');
}
return (
<form className="AddThoughtForm" onSubmit={handleSubmit}>
<input
type="text"
aria-label="What's on your mind?"
placeholder="What's on your mind?"
value={text}
onChange={handleTextChange}
/>
<input type="submit" value="Add" />
</form>
);
}
You can access the props in AppThoughtForm in two ways. One way is to do like what was already done in the Thought component with this line of code (using Object destructuring):
const { thought, removeThought } = props;
Since this was used in the Thought component you can see that thought or removeThought is simply referenced in the Thought component where the prop was passed in. But if you don’t use Object destructuring then you can instead access the props with props.thought or props.removeThought (in this example). So you can apply the same technique in AppThoughtForm when accessing the addThought function as a prop. Either use props.addThought or do the object destructuring.
useEffect(() => {
let timeRemaining = thought.expiresAt - Date.now();
let timeoutId = setTimeout(() => {
alert('Time has passed!');
}, timeRemaining);
return () => {
clearTimeout(timeoutId);
}
}, [thought]);
It says to " add [thought] as a dependency so the effect re-runs every time the thought is different." But a thought never changes before it gets deleted, and the cleanup function should be called when the component is unmounted.
Hello guys,
I basically finished the project but there is one problem: I cannot add a new thought, I was able at some point but nothing was displayed in it and now it just seems like every time I create a new one it gets automatically deleted!
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';
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(),
},
]);
const addThought = (thought) =>{
setThoughts((thought)=>[thought,
...thoughts]);
};
const removeThought = (thoughtIdToRemove) =>{
setThoughts((thoughts) => thoughts.filter((thought) => thought.id !== thoughtIdToRemove));
}
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>
);
}
ReactDOM.render(<App />, document.getElementById('app'));
Hey Guys I ahve been working with this and after reading all teh discussion still not so cleared to me Why I am not able make it work properly. I hope anybody can help me with this part, I’ll be more than glad
//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';
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(),
},
]);
const addThought = (thought) => {
setThoughts((thoughts) => [thought, ...thoughts]);
};
const removeThought = (thoughtIdToRemove) => {
setThoughts((thoughts) => thoughts.filter((thought) =>
thought.id !== thoughtIdToRemove
));
};
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>
);
}
ReactDOM.render(<App />, document.getElementById('app'));
//AddThoughtForm.js
import React, { useState } from 'react';
import { generateId, getNewExpirationTime } from './utilities';
export function AddThoughtForm(props) {
const [text, setText] = useState('');
const handleTextChange = (event) => {
setText(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
if (text.length > 0) {
const thought = {
id: generateId(),
text: text,
expiresAt: getNewExpirationTime()
};
props.addThought(thought);
setText('');
};
};
export function AddThoughtForm(props) {
return (
<form className="AddThoughtForm" onSubmit={handleSubmit}>
<input
value={text}
onChange={handleTextChange}
onSubmit={handleSubmit}
type="text"
aria-label="What's on your mind?"
placeholder="What's on your mind?"
/>
<input type="submit" value="Add" />
</form>
);
}
Thank you so much for the help as I was having a very similar problem. This project is very buggy - it didn’t work until I used your code. I followed the video steps and the formatter for weeks and it wouldn’t work.