-
Notifications
You must be signed in to change notification settings - Fork 44
Sphinx - Vlada Rapaport #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,34 @@ | ||
| import { useState } from 'react'; | ||
| import './App.css'; | ||
| import ChatLog from './components/ChatLog'; | ||
| import messages from './data/messages.json'; | ||
|
|
||
| const App = () => { | ||
| const [counter, setCounter] = useState(0); // Initial counter set to 0 | ||
|
|
||
| const onLike = () => { | ||
| setCounter((prevCounter) => prevCounter + 1); | ||
| }; | ||
|
|
||
| const onUnlike = () => { | ||
| setCounter((prevCounter) => prevCounter - 1); | ||
| }; | ||
|
Comment on lines
+9
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of two methods for handling liking and unliking a ChatEntry, you can write an event handler that handles both scenarios. That would look something like having an event handler that changes the state of the const handleLikeData = (id) => {
const updatedEntries = chatMessages.map(chatMessage => {
if (chatMessage.id === id) {
return { ...chatMessage, liked: !chatMessage.liked };
}
else {
return chatMessage;
}
})
setChatMessages(updatedEntries);
};
const calculateTotalLikes = () =>
return chatMessages.reduce((totalLikes, chatMessage) => (totalLikes + chatMessage.liked), 0);
};You can see how we do this with pets on a Cat in flasky here. |
||
|
|
||
| const likes = counter + ' ❤️s'; | ||
|
|
||
| return ( | ||
| <div id="App"> | ||
| <header> | ||
| <h2>{likes}</h2> | ||
| <h1>Application title</h1> | ||
| </header> | ||
| <main> | ||
| {/* Wave 01: Render one ChatEntry component | ||
| Wave 02: Render ChatLog component */} | ||
| { | ||
| <ChatLog | ||
| entries={messages} | ||
| onLike={onLike} | ||
| onUnlike={onUnlike} /> | ||
| } | ||
| </main> | ||
| </div> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,20 +1,39 @@ | ||||||
| import { useState } from 'react'; | ||||||
| import PropTypes from 'prop-types'; | ||||||
| import './ChatEntry.css'; | ||||||
| import TimeStamp from './TimeStamp'; | ||||||
|
|
||||||
| const ChatEntry = ({sender, body, timeStamp, onLike, onUnlike}) => { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Should have white spaces around curly braces when using destructuring syntax. I'd also expect |
||||||
| const [buttonText, setButtonText] = useState('🤍'); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't need to use |
||||||
|
|
||||||
| const onLikeClick = () => { | ||||||
| if (buttonText === '🤍') { | ||||||
| setButtonText('❤️'); | ||||||
| onLike(); | ||||||
| } else { | ||||||
| setButtonText('🤍'); | ||||||
| onUnlike(); | ||||||
| } | ||||||
| }; | ||||||
|
Comment on lines
+9
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I'd like to see I'd like to see is an event handler written in app and this event handler would be passed down through props from
This is similar to how we implemented the pet-a-cat button in the |
||||||
|
|
||||||
| const ChatEntry = () => { | ||||||
| return ( | ||||||
| <div className="chat-entry local"> | ||||||
| <h2 className="entry-name">Replace with name of sender</h2> | ||||||
| <h2 className="entry-name">{sender}</h2> | ||||||
| <section className="entry-bubble"> | ||||||
| <p>Replace with body of ChatEntry</p> | ||||||
| <p className="entry-time">Replace with TimeStamp component</p> | ||||||
| <button className="like">🤍</button> | ||||||
| <p>{body}</p> | ||||||
| <p className="entry-time"><TimeStamp time ={timeStamp} /></p> | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Nice job using the provided Timestamp component here. Convention is to not have spaces around = sign when passing props |
||||||
| <button className="like" onClick={onLikeClick}>{buttonText}</button> | ||||||
| </section> | ||||||
| </div> | ||||||
| ); | ||||||
| }; | ||||||
|
|
||||||
| ChatEntry.propTypes = { | ||||||
| // Fill with correct proptypes | ||||||
| sender: PropTypes.string.isRequired, | ||||||
| body: PropTypes.string.isRequired, | ||||||
| timeStamp: PropTypes.elementType.isRequired, | ||||||
| onLike: PropTypes.func.isRequired, | ||||||
| onUnlike: PropTypes.func.isRequired, | ||||||
| }; | ||||||
|
|
||||||
| export default ChatEntry; | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,34 @@ | ||||||
| import PropTypes from 'prop-types'; | ||||||
| import './ChatLog.css'; | ||||||
| import ChatEntry from './ChatEntry'; | ||||||
|
|
||||||
| const ChatLog = ({entries, onLike, onUnlike}) => { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| return ( | ||||||
| <div> | ||||||
| {entries.map((entry) => ( | ||||||
| <ChatEntry | ||||||
| key={entry.id} | ||||||
| sender={entry.sender} | ||||||
| body={entry.body} | ||||||
| timeStamp={entry.timeStamp} | ||||||
| onLike={onLike} | ||||||
| onUnlike={onUnlike} | ||||||
| /> | ||||||
| ))} | ||||||
| </div> | ||||||
| ); | ||||||
| }; | ||||||
|
Comment on lines
+6
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's more typical to see the result of using const chatEntries = entries.map((entry) => {
return (
<ChatEntry
key={entry.id}
id={entry.id}
sender={entry.sender}
body={entry.body}
timeStamp={entry.timeStamp}
liked={entry.liked}
handleLike={handleLike}
currentUser={currentUser}
/>
);
});
};
return (
<div>
{chatEntries}
</div>
); |
||||||
|
|
||||||
| ChatLog.propTypes = { | ||||||
| entries: PropTypes.arrayOf( | ||||||
| PropTypes.shape({ | ||||||
| sender: PropTypes.string.isRequired, | ||||||
| body: PropTypes.string.isRequired, | ||||||
| timeStamp: PropTypes.node.isRequired, | ||||||
| }).isRequired | ||||||
| ).isRequired, | ||||||
| onLike: PropTypes.func.isRequired, | ||||||
| onUnlike: PropTypes.func.isRequired, | ||||||
| }; | ||||||
|
|
||||||
| export default ChatLog; | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer not to have comments in code unless absolutely necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per the pattern we did during the flasky-front-end livecode and what we hope to see in the task-list-front-end activity, we want state to keep track of
ChatEntrys here. Or in flasky-front-end, the state in App.jsx kept track of individualCats and in task-list-front-end the state in App.jsx should keep track ofTasks. We want our whole app to know that a single component has been updated so we had to lift that state up to App.jsx.You haven't lifted state up from the individual
ChatEntryup intoAppin this project. You do use state, but we don't need state to keep track of a count of the hearts. We can calculate this value from each ChatEntry. If a value can be calculated, then we should prefer not to use state to handle this logic.We want App.jsx to know a change has happened to
ChatEntryso that React knows to re-render the each ChatEntry.This is the state we'd like to see implemented.