Code
Code
js
import React, { useReducer, useEffect } from 'react';
import reducer, { initialState } from '../state/reducer';
import Context from '../context';
import PubSub from '../pubsub';
import PublishMessage from './PublishMessage';
import MessageBoard from './MessageBoard';
import SetUsername from './SetUsername';
const pubsub = new PubSub();
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
pubsub.addListener({
message: messageObject => {
const { channel, message } = messageObject;
CreateReaction.js
import React from 'react';
import { REACTION_OBJECTS } from '../state/types';
import { useAppContext } from './hooks';
import { createReaction } from '../state/actions';
function CreateReaction({ messageId }) {
const { state: { username }, pubsub: { publish } } = useAppContext();
const publishReaction = ({ type, emoji }) => () => {
publish(createReaction({ type, emoji, username, messageId }));
}return (
<div className='CreateReaction'>
{
REACTION_OBJECTS.map(REACTION_OBJECT => {
const { type, emoji } = REACTION_OBJECT;
return (
<span
key={type}
onClick={publishReaction({ type, emoji })}
>
{emoji}
</span>
)})} </div>)}
export default CreateReaction;
hook.js
Import { useContext } from 'react';
import Context from '../context';
export const useAppContext = () => {
return useContext(Context);}
MessageBoard.js
import React from 'react';
import { useAppContext } from './hooks';
import CreateReaction from './CreateReaction';
import MessageReactions from './MessageReactions';
function MessageBoard() {
const { state: { messages, reactionsMap } } = useAppContext();
return (
<div>
{ messages.map(messageItem => {
const { id, text, username, timestamp } = messageItem;
return (
<div key={id}>
<h4>{new Date(timestamp).toLocaleString()}</h4>
<p>{text}</p>
<h4>- {username}</h4>
<CreateReaction messageId={id} />
<MessageReactions messageReactions={reactionsMap[id]} />
<hr />
</div>
)}) }</div>)}
xport default MessageBoard;
MessageReaction.js
import React from 'react';
return (
messageReactions.map((reaction, index) => {
const { id, emoji, username } = reaction;
return (
<span key={id}>
<em>{username}: </em>
{emoji}
{index !== messageReactions.length-1 ? ', ' : null}
</span> )}))}
export default MessageReactions;
PublishMessage.js
import React, { useState } from 'react';
import { useAppContext } from './hooks';
import { newMessage } from '../state/actions';
function PublishMessage() {
const { state: { username }, pubsub: { publish } } = useAppContext();
const [text, setText] = useState('');
return (
<div>
<h3>Got something to say?</h3>
<input value={text} onChange={updateText} onKeyPress={handleKeyPress} />
{' '}
<button onClick={publishMessage}>Publish it!</button>
</div>
)
}
export default PublishMessage;
SetUsername.js
import React from 'react';
import { useAppContext } from './hooks';
import { setUsername } from '../state/actions';
function SetUsername() {
const { state: { username }, dispatch } = useAppContext();
return (
<div>
<h3>Username</h3>
<input onChange={updateUsername} value={username} />
</div>
)
};
export default SetUsername ;
Action.js
import { NEW_MESSAGE, SET_USERNAME } from './types';
import uuid from 'uuid/v4';
if (REACTION_TYPES.includes(action.type)) {
let reactionsMap;
const { messageId } = action.item;
const messageReactions = state.reactionsMap[messageId];
if (messageReactions) {
reactionsMap = {
...state.reactionsMap,
[messageId]: [...messageReactions, action.item]
}
} else {
reactionsMap = {
...state.reactionsMap,
[messageId]: [action.item]
}
}
switch(action.type) {
case NEW_MESSAGE:
return { ...state, messages: [...state.messages, action.item] };
case SET_USERNAME:
return { ...state, username: action.username }
default:
return state;
}
}
export default reducer;
type.js
export const NEW_MESSAGE = 'NEW_MESSAGE';
export const SET_USERNAME = 'SET_USERNAME';
export const REACTION_OBJECTS = [
{
},
❤️
type: 'REACTION_LOVE',
emoji: ' '
},
👍
type: 'REACTION_LIKE',
emoji: ' '
},
👎
type: 'REACTION_DISLIKE',
emoji: ' '
}
😂
type: 'REACTION_LAUGH',
emoji: ' '
];
context.js
import { createContext } from 'react';
export default createContext();
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( <App />);
pubsub.js
import PubNub from 'pubnub';
import pubnubConfig from './pubnub.config';
function PubSub() {
const pubnub = new PubNub(pubnubConfig);
pubnub.publish({
message,
channel: MESSAGE_CHANNEL
});
}}
export default PubSub;
pubsum.js
import PubNub from "pubNub";
import PubnubConfig from "./pubnub.config";
pubnub.subscribe({channels:[MESSAGE_CHANNEL]});
pubnub.addListener({
message :messageObject =>{
console.log('messageObject',messageObject);
}
});
setTimeout(()=>{},1000);
pubnub.publish({
message:'foo',
channel:MESSAGE_CHANNEL});