From dd4007b865b7eaa209aab48dafb3832d211017c7 Mon Sep 17 00:00:00 2001 From: Jerome Olvera Date: Tue, 11 Jan 2022 22:09:10 -0600 Subject: [PATCH 1/4] basic features refactor --- src/App.tsx | 24 ++---------------- .../chats}/LiveChat.tsx | 2 +- .../chats}/Message.tsx | 0 src/{hooks => features/chats}/useMessages.ts | 0 .../comment}/Comments.tsx | 0 src/{ => features}/components/NavBar.tsx | 0 .../video-player}/VideoPlayer.tsx | 0 src/features/watch/Watch.tsx | 25 +++++++++++++++++++ 8 files changed, 28 insertions(+), 23 deletions(-) rename src/{components => features/chats}/LiveChat.tsx (88%) rename src/{components => features/chats}/Message.tsx (100%) rename src/{hooks => features/chats}/useMessages.ts (100%) rename src/{components => features/comment}/Comments.tsx (100%) rename src/{ => features}/components/NavBar.tsx (100%) rename src/{components => features/video-player}/VideoPlayer.tsx (100%) create mode 100644 src/features/watch/Watch.tsx diff --git a/src/App.tsx b/src/App.tsx index 8a0f872..b67db3b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,25 +1,5 @@ -import NavBar from "./components/NavBar"; -import VideoPlayer from "./components/VideoPlayer"; -import LiveChat from "./components/LiveChat"; -import Comments from "./components/Comments"; +import Watch from "./features/watch/Watch"; export default function App() { - return ( - <> - -
-
-
- -
-
- -
-
-
- -
-
- - ); + return ; } diff --git a/src/components/LiveChat.tsx b/src/features/chats/LiveChat.tsx similarity index 88% rename from src/components/LiveChat.tsx rename to src/features/chats/LiveChat.tsx index 7ef6130..ab4630e 100644 --- a/src/components/LiveChat.tsx +++ b/src/features/chats/LiveChat.tsx @@ -1,4 +1,4 @@ -import useMessages from "../hooks/useMessages"; +import useMessages from "./useMessages"; import Message from "./Message"; export default function LiveChat() { diff --git a/src/components/Message.tsx b/src/features/chats/Message.tsx similarity index 100% rename from src/components/Message.tsx rename to src/features/chats/Message.tsx diff --git a/src/hooks/useMessages.ts b/src/features/chats/useMessages.ts similarity index 100% rename from src/hooks/useMessages.ts rename to src/features/chats/useMessages.ts diff --git a/src/components/Comments.tsx b/src/features/comment/Comments.tsx similarity index 100% rename from src/components/Comments.tsx rename to src/features/comment/Comments.tsx diff --git a/src/components/NavBar.tsx b/src/features/components/NavBar.tsx similarity index 100% rename from src/components/NavBar.tsx rename to src/features/components/NavBar.tsx diff --git a/src/components/VideoPlayer.tsx b/src/features/video-player/VideoPlayer.tsx similarity index 100% rename from src/components/VideoPlayer.tsx rename to src/features/video-player/VideoPlayer.tsx diff --git a/src/features/watch/Watch.tsx b/src/features/watch/Watch.tsx new file mode 100644 index 0000000..2015452 --- /dev/null +++ b/src/features/watch/Watch.tsx @@ -0,0 +1,25 @@ +import NavBar from "../components/NavBar"; +import VideoPlayer from "../video-player/VideoPlayer"; +import LiveChat from "../chats/LiveChat"; +import Comments from "../comment/Comments"; + +export default function App() { + return ( + <> + +
+
+
+ +
+
+ +
+
+
+ +
+
+ + ); +} From 31ff45605c1af150a020ae1c96ade320ee72b70d Mon Sep 17 00:00:00 2001 From: Jerome Olvera Date: Thu, 13 Jan 2022 20:08:06 -0600 Subject: [PATCH 2/4] add LiveChat state --- src/features/chats/LiveChat.test.tsx | 34 ++++++++++++ src/features/chats/LiveChat.tsx | 60 +++++++++++++++++++--- src/features/chats/LiveChatContainer.tsx | 5 ++ src/features/chats/Message.tsx | 2 +- src/features/chats/MessageRestProvider.tsx | 20 ++++++++ src/features/chats/MessagesProvider.tsx | 11 ++++ src/features/chats/useMessages.ts | 16 ------ src/features/createContextValue.tsx | 46 +++++++++++++++++ src/features/watch/Watch.tsx | 5 +- 9 files changed, 175 insertions(+), 24 deletions(-) create mode 100644 src/features/chats/LiveChat.test.tsx create mode 100644 src/features/chats/LiveChatContainer.tsx create mode 100644 src/features/chats/MessageRestProvider.tsx create mode 100644 src/features/chats/MessagesProvider.tsx delete mode 100644 src/features/chats/useMessages.ts create mode 100644 src/features/createContextValue.tsx diff --git a/src/features/chats/LiveChat.test.tsx b/src/features/chats/LiveChat.test.tsx new file mode 100644 index 0000000..c723cc6 --- /dev/null +++ b/src/features/chats/LiveChat.test.tsx @@ -0,0 +1,34 @@ +import { render, screen } from "@testing-library/react"; + +import LiveChat from "./LiveChat"; +import { MessagesProvider } from "./MessagesProvider"; + +test("list messages in chat", () => { + // arrange + const messages = [ + { + id: "1", + text: "Hello, how are you?", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + { + id: "2", + text: "I'm fine, thank you!", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + ]; + + // act + render( + + + + ); + + // assert + messages.forEach((message) => { + expect(screen.getByText(message.text)).toBeInTheDocument(); + }); +}); diff --git a/src/features/chats/LiveChat.tsx b/src/features/chats/LiveChat.tsx index ab4630e..0cb63ad 100644 --- a/src/features/chats/LiveChat.tsx +++ b/src/features/chats/LiveChat.tsx @@ -1,17 +1,65 @@ -import useMessages from "./useMessages"; +import { useState } from "react"; import Message from "./Message"; export default function LiveChat() { - const messages = useMessages(); + const [messages, setMessages] = useState([ + { + id: "1", + text: "Hello, how are you?", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + { + id: "2", + text: "I'm fine, thank you!", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + ]); + + function handleNewMessage(e: React.FormEvent) { + e.preventDefault(); + const form = e.currentTarget; + const formElements = form.elements as typeof form.elements & { + message: { value: string }; + }; + + setMessages((prevMessages) => { + return [ + ...prevMessages, + { + id: `${Date.now()}`, + text: formElements.message.value, + user: "John", + timestamp: new Date().toISOString(), + }, + ]; + }); + } return (
- {messages.map((message) => ( - - ))} +
+

Live Chat

+
+
+ {messages.map((message) => ( + + ))} +
+
+ +
); } diff --git a/src/features/chats/LiveChatContainer.tsx b/src/features/chats/LiveChatContainer.tsx new file mode 100644 index 0000000..c63f158 --- /dev/null +++ b/src/features/chats/LiveChatContainer.tsx @@ -0,0 +1,5 @@ +import LiveChat from "./LiveChat"; + +export default function LiveChatContainer() { + return ; +} diff --git a/src/features/chats/Message.tsx b/src/features/chats/Message.tsx index 9ca60a6..0e563d8 100644 --- a/src/features/chats/Message.tsx +++ b/src/features/chats/Message.tsx @@ -1,3 +1,3 @@ export default function Message({ text }: any) { - return
{text}
; + return
{text}
; } diff --git a/src/features/chats/MessageRestProvider.tsx b/src/features/chats/MessageRestProvider.tsx new file mode 100644 index 0000000..841484a --- /dev/null +++ b/src/features/chats/MessageRestProvider.tsx @@ -0,0 +1,20 @@ +import { MessagesProvider } from "./MessagesProvider"; + +export default function MessageRestProvider({ children }: any) { + const messages = [ + { + id: "1", + text: "Hello, how are you?", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + { + id: "2", + text: "I'm fine, thank you!", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + ]; + + return {children}; +} diff --git a/src/features/chats/MessagesProvider.tsx b/src/features/chats/MessagesProvider.tsx new file mode 100644 index 0000000..93f88fb --- /dev/null +++ b/src/features/chats/MessagesProvider.tsx @@ -0,0 +1,11 @@ +import createContextValue from "../createContextValue"; + +type MessagesValue = { + id: string; + text: string; + user: string; + timestamp: string; +}; + +export const [MessagesProvider, useMessagesValue] = + createContextValue>("MessagesProvider"); diff --git a/src/features/chats/useMessages.ts b/src/features/chats/useMessages.ts deleted file mode 100644 index 45d5dd9..0000000 --- a/src/features/chats/useMessages.ts +++ /dev/null @@ -1,16 +0,0 @@ -export default function useMessages() { - return [ - { - id: 1, - text: "Hello, how are you?", - user: "John", - timestamp: "2020-01-01T00:00:00.000Z", - }, - { - id: 2, - text: "I'm fine, thank you!", - user: "John", - timestamp: "2020-01-01T00:00:00.000Z", - }, - ]; -} diff --git a/src/features/createContextValue.tsx b/src/features/createContextValue.tsx new file mode 100644 index 0000000..afdfcfe --- /dev/null +++ b/src/features/createContextValue.tsx @@ -0,0 +1,46 @@ +import React, { useContext, useMemo } from "react"; + +/** + * creates a Context provider and consumer hook to a provided value. + */ +export default function createContextValue( + name: string, + defaultValue: T | undefined = undefined +) { + const ValueContext = React.createContext(defaultValue); + + type ProviderProps = { + children: React.ReactNode; + value?: T; + }; + + /** + * Provides the value of the context. + * It memoizes the provided value and recompute when `value` changes. + */ + function Provider({ value, children }: ProviderProps) { + const contextValue = useMemo(() => value ?? defaultValue, [value]); + return ( + + {children} + + ); + } + + /** + * Reads the value of the context. + * Throws an error if the component is not wrapped in a Provider + * or if the context value is strictly undefined. + */ + function useValue() { + const contextValue = useContext(ValueContext); + if (contextValue === undefined) { + throw new Error( + `use ${name} must be used within a ${name} value provider` + ); + } + return contextValue; + } + + return [Provider, useValue] as const; +} diff --git a/src/features/watch/Watch.tsx b/src/features/watch/Watch.tsx index 2015452..963c25f 100644 --- a/src/features/watch/Watch.tsx +++ b/src/features/watch/Watch.tsx @@ -2,6 +2,7 @@ import NavBar from "../components/NavBar"; import VideoPlayer from "../video-player/VideoPlayer"; import LiveChat from "../chats/LiveChat"; import Comments from "../comment/Comments"; +import MessageRestProvider from "../chats/MessageRestProvider"; export default function App() { return ( @@ -13,7 +14,9 @@ export default function App() {
- + + +
From fde08033590efd7effb6ba89eb98d4f9fce5b069 Mon Sep 17 00:00:00 2001 From: Jerome Olvera Date: Thu, 13 Jan 2022 20:13:13 -0600 Subject: [PATCH 3/4] extract basic form state --- src/features/chats/LiveChat.test.tsx | 2 +- src/features/chats/LiveChat.tsx | 41 ++++++++---------------- src/features/chats/LiveChatContainer.tsx | 32 +++++++++++++++++- src/features/watch/Watch.tsx | 4 +-- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/src/features/chats/LiveChat.test.tsx b/src/features/chats/LiveChat.test.tsx index c723cc6..21d847a 100644 --- a/src/features/chats/LiveChat.test.tsx +++ b/src/features/chats/LiveChat.test.tsx @@ -23,7 +23,7 @@ test("list messages in chat", () => { // act render( - + ); diff --git a/src/features/chats/LiveChat.tsx b/src/features/chats/LiveChat.tsx index 0cb63ad..7b2bbd1 100644 --- a/src/features/chats/LiveChat.tsx +++ b/src/features/chats/LiveChat.tsx @@ -1,40 +1,26 @@ -import { useState } from "react"; import Message from "./Message"; -export default function LiveChat() { - const [messages, setMessages] = useState([ - { - id: "1", - text: "Hello, how are you?", - user: "John", - timestamp: "2020-01-01T00:00:00.000Z", - }, - { - id: "2", - text: "I'm fine, thank you!", - user: "John", - timestamp: "2020-01-01T00:00:00.000Z", - }, - ]); +type LiveChatProps = { + addNewMessage?: (message: string) => void; + messages: ReadonlyArray<{ + id: string; + text: string; + user: string; + timestamp: string; + }>; +}; +export default function LiveChat({ messages, addNewMessage }: LiveChatProps) { function handleNewMessage(e: React.FormEvent) { e.preventDefault(); + const form = e.currentTarget; const formElements = form.elements as typeof form.elements & { message: { value: string }; }; - setMessages((prevMessages) => { - return [ - ...prevMessages, - { - id: `${Date.now()}`, - text: formElements.message.value, - user: "John", - timestamp: new Date().toISOString(), - }, - ]; - }); + addNewMessage!(formElements.message.value); + form.reset(); } return ( @@ -53,6 +39,7 @@ export default function LiveChat() {
; + const [messages, setMessages] = useState([ + { + id: "1", + text: "Hello, how are you?", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + { + id: "2", + text: "I'm fine, thank you!", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + ]); + + function handleAddNewMessage(message: string) { + setMessages((prevMessages) => { + return [ + ...prevMessages, + { + id: `${Date.now()}`, + text: message, + user: "John", + timestamp: new Date().toISOString(), + }, + ]; + }); + } + + return ; } diff --git a/src/features/watch/Watch.tsx b/src/features/watch/Watch.tsx index 963c25f..72765fd 100644 --- a/src/features/watch/Watch.tsx +++ b/src/features/watch/Watch.tsx @@ -1,6 +1,6 @@ import NavBar from "../components/NavBar"; import VideoPlayer from "../video-player/VideoPlayer"; -import LiveChat from "../chats/LiveChat"; +import LiveChatContainer from "../chats/LiveChatContainer"; import Comments from "../comment/Comments"; import MessageRestProvider from "../chats/MessageRestProvider"; @@ -15,7 +15,7 @@ export default function App() {
- +
From 76df16aff598d7396e9b7f18128d05d95bc4255c Mon Sep 17 00:00:00 2001 From: Jerome Olvera Date: Thu, 13 Jan 2022 20:15:37 -0600 Subject: [PATCH 4/4] remove unused dependencies --- src/features/chats/LiveChat.test.tsx | 34 ------------------- src/features/chats/LiveChatContainerRest.tsx | 35 ++++++++++++++++++++ src/features/chats/MessageRestProvider.tsx | 20 ----------- src/features/watch/Watch.tsx | 5 +-- 4 files changed, 36 insertions(+), 58 deletions(-) delete mode 100644 src/features/chats/LiveChat.test.tsx create mode 100644 src/features/chats/LiveChatContainerRest.tsx delete mode 100644 src/features/chats/MessageRestProvider.tsx diff --git a/src/features/chats/LiveChat.test.tsx b/src/features/chats/LiveChat.test.tsx deleted file mode 100644 index 21d847a..0000000 --- a/src/features/chats/LiveChat.test.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { render, screen } from "@testing-library/react"; - -import LiveChat from "./LiveChat"; -import { MessagesProvider } from "./MessagesProvider"; - -test("list messages in chat", () => { - // arrange - const messages = [ - { - id: "1", - text: "Hello, how are you?", - user: "John", - timestamp: "2020-01-01T00:00:00.000Z", - }, - { - id: "2", - text: "I'm fine, thank you!", - user: "John", - timestamp: "2020-01-01T00:00:00.000Z", - }, - ]; - - // act - render( - - - - ); - - // assert - messages.forEach((message) => { - expect(screen.getByText(message.text)).toBeInTheDocument(); - }); -}); diff --git a/src/features/chats/LiveChatContainerRest.tsx b/src/features/chats/LiveChatContainerRest.tsx new file mode 100644 index 0000000..8b178ff --- /dev/null +++ b/src/features/chats/LiveChatContainerRest.tsx @@ -0,0 +1,35 @@ +import { useState } from "react"; +import LiveChat from "./LiveChat"; + +export default function LiveChatContainer() { + const [messages, setMessages] = useState([ + { + id: "1", + text: "Hello, how are you?", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + { + id: "2", + text: "I'm fine, thank you!", + user: "John", + timestamp: "2020-01-01T00:00:00.000Z", + }, + ]); + + function handleAddNewMessage(message: string) { + setMessages((prevMessages) => { + return [ + ...prevMessages, + { + id: `${Date.now()}`, + text: message, + user: "John", + timestamp: new Date().toISOString(), + }, + ]; + }); + } + + return ; +} diff --git a/src/features/chats/MessageRestProvider.tsx b/src/features/chats/MessageRestProvider.tsx deleted file mode 100644 index 841484a..0000000 --- a/src/features/chats/MessageRestProvider.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { MessagesProvider } from "./MessagesProvider"; - -export default function MessageRestProvider({ children }: any) { - const messages = [ - { - id: "1", - text: "Hello, how are you?", - user: "John", - timestamp: "2020-01-01T00:00:00.000Z", - }, - { - id: "2", - text: "I'm fine, thank you!", - user: "John", - timestamp: "2020-01-01T00:00:00.000Z", - }, - ]; - - return {children}; -} diff --git a/src/features/watch/Watch.tsx b/src/features/watch/Watch.tsx index 72765fd..2d6841e 100644 --- a/src/features/watch/Watch.tsx +++ b/src/features/watch/Watch.tsx @@ -2,7 +2,6 @@ import NavBar from "../components/NavBar"; import VideoPlayer from "../video-player/VideoPlayer"; import LiveChatContainer from "../chats/LiveChatContainer"; import Comments from "../comment/Comments"; -import MessageRestProvider from "../chats/MessageRestProvider"; export default function App() { return ( @@ -14,9 +13,7 @@ export default function App() {
- - - +