Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import React from 'react';
import React, { useState } from 'react';
import './App.css';
import chatMessages from './data/messages.json';
import ChatLog from './components/ChatLog';

const App = () => {
const [likedMessages, setLikedMessages] = useState(0);

const likeMessage = () => {
setLikedMessages(likedMessages => likedMessages + 1);
};

const unlikeMessage = () => {
setLikedMessages(likedMessages => likedMessages - 1);
};
Comment on lines +9 to +15

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can actually keep track of the number of likes across all the messages without using state, thus we should prefer to not use state to reduce the complexity of the project.

Instead, you can create a function that iterates over all the chats and adds up the number of likes, something like:

const getHeartCount = () => {
    return chatMessages.reduce((total, chat) => {
      return chat.liked ? total + 1 : total;
    }, 0)
};

// then on line 21, you can write this:
<h2>{getHeartCount()} ❤️s</h2>

This approach for calculating the total likes across all messages, would require you to keep track of the messages as state though and you'd need an event handler for updating when a message is liked. I'll leave more details about that in another comment.


return (
<div id="App">
<header>
<h1>Application title</h1>
<h1>Chat Messages</h1>
<h2>{likedMessages} ❤️s</h2>
</header>
<main>
{/* Wave 01: Render one ChatEntry component
Wave 02: Render ChatLog component */}
<ChatLog
entries={chatMessages}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of just passing in chatMessages from the messages.json file, we should use state as a single source of truth for keeping track of the data related to messages. Therefore, we should have a piece of state on line 8 like:

const [chatMessageData, setChatMessagData] = useState(chatMessages);

You'd also need an event handler that you can pass down to ChatEntry.js that would help you toggle the liked value on a single chat. It would be better for the logic about how to copy the message and change the liked status to be written in App.js

const updateEntryData = id => {
const entries = chatMessageData.map(entry => {
      if (entry.id === id){
        return {...entry, liked: !entry.liked};
      } 
      else {
        return entry;
      }
    });
    setChatMessagData(entries);
}

likeMessage={likeMessage}
unlikeMessage={unlikeMessage}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following my comment above about creating an event handler in app.js to help you keep track of a message's 'liked' status, you would need to pass that event handler from App to ChatLog and finally into ChatEntry.

<ChatLog
    entries={chatMessageData}
    updateEntryData={updateEntryData}
/>

/>
</main>
</div>
);
Expand Down
32 changes: 25 additions & 7 deletions src/components/ChatEntry.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
import React from 'react';
import React, { useState } from 'react';
import './ChatEntry.css';
import TimeStamp from './TimeStamp';
import PropTypes from 'prop-types';

const ChatEntry = (props) => {
const ChatEntry = ( { sender, body, timeStamp, likeMessage, unlikeMessage } ) => {
const [hearted, setHearted] = useState(false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need state here to keep track of a message's 'liked' status.


const toggleHeart = () => {
setHearted(hearted => !hearted);
hearted ? unlikeMessage(): likeMessage();
};
Comment on lines +9 to +12

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following my suggestion about passing down an event handler that can be used to change a message's 'liked' status, you would use that event handler in toggleHeart here:

  const toggleHeart = () => {
    props.updateEntryData(props.id);
  };


const heartedIcon = hearted ? '❤️' : '🤍';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


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}/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job using the provided TimeStamp component

</p>
<button className="like" onClick={() => toggleHeart()}>
{heartedIcon}
</button>
</section>
</div>
);
};

ChatEntry.propTypes = {
//Fill with correct proptypes
id: PropTypes.number.isRequired,
sender: PropTypes.string.isRequired,
body: PropTypes.number.isRequired,
timeStamp: PropTypes.string.isRequired,
liked: PropTypes.bool.isRequired
Comment on lines +33 to +37

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

propTypes is missing a couple values that are passed in from ChatLog to ChatEntry: likeMessage and unlikeMessage

};

export default ChatEntry;
32 changes: 32 additions & 0 deletions src/components/ChatLog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import './ChatLog.css';
import PropTypes from 'prop-types';
import ChatEntry from './ChatEntry';

const ChatLog = ( { entries, likeMessage, unlikeMessage } ) => {
const chatEntries = entries.map(entry => {
return (
<ChatEntry
id={entry.id}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also use the id for the key prop since we're iterating over many entries to create many ChatEntrys:

 <ChatEntry
     id={entry.id}
     key={entry.id}
     // the rest of your props for your component
/>

sender={entry.sender}
body={entry.body}
timeStamp={entry.timeStamp}
liked={entry.liked}
likeMessage={likeMessage}
unlikeMessage={unlikeMessage}
/>
)
})

return (
<>
{chatEntries}
</>
)
};

ChatLog.propTypes = {
entries: PropTypes.array.isRequired
};
Comment on lines +28 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be sure to write out the full propTypes in the future to include shapeOf


export default ChatLog;