From 75c0694c03912c376569062dada792acfd75f2cd Mon Sep 17 00:00:00 2001 From: zikaeroh <48577114+zikaeroh@users.noreply.github.com> Date: Thu, 28 May 2020 20:34:11 -0700 Subject: [PATCH] Optimize the remaining rerenders --- frontend/src/components/clipboard.tsx | 5 +- frontend/src/pages/gameView.tsx | 250 ++++++++++++++++---------- 2 files changed, 160 insertions(+), 95 deletions(-) diff --git a/frontend/src/components/clipboard.tsx b/frontend/src/components/clipboard.tsx index 27caf6d..34ac8af 100644 --- a/frontend/src/components/clipboard.tsx +++ b/frontend/src/components/clipboard.tsx @@ -1,6 +1,7 @@ import { Button, Tooltip } from '@material-ui/core'; import copy from 'clipboard-copy'; import * as React from 'react'; +import isEqual from 'react-fast-compare'; export interface ClipboardButtonProps { buttonText: string; @@ -8,7 +9,7 @@ export interface ClipboardButtonProps { icon: React.ReactNode; } -export const ClipboardButton = (props: ClipboardButtonProps) => { +export const ClipboardButton = React.memo(function ClipboardButton(props: ClipboardButtonProps) { const [showTooltip, setShowTooltip] = React.useState(false); return ( @@ -30,4 +31,4 @@ export const ClipboardButton = (props: ClipboardButtonProps) => { ); -}; +}, isEqual); diff --git a/frontend/src/pages/gameView.tsx b/frontend/src/pages/gameView.tsx index d99bb78..a9edba6 100644 --- a/frontend/src/pages/gameView.tsx +++ b/frontend/src/pages/gameView.tsx @@ -73,7 +73,13 @@ const useCenterStyles = makeStyles((_theme: Theme) => }) ); -const CenterText = ({ winner, timer, turn }: State) => { +interface CenterTextProps { + winner: number | undefined | null; + timer: StateTimer | undefined | null; + turn: number; +} + +const CenterText = ({ winner, timer, turn }: DeepReadonly) => { const classes = useCenterStyles(); const [countdown, setCountdown] = React.useState(); const { now } = useServerTime(); @@ -135,21 +141,37 @@ const CenterText = ({ winner, timer, turn }: State) => { ); }; -const Header = ({ send, state, pState, pTeam }: GameViewProps) => { - const myTurn = state.turn === pTeam; +interface HeaderProps { + send: Sender; + myTurn: boolean; + winner: number | undefined | null; + spymaster: boolean; + turn: number; + wordsLeft: number[]; + timer: StateTimer | undefined | null; +} +const Header = React.memo(function Header({ + send, + myTurn, + winner, + spymaster, + turn, + wordsLeft, + timer, +}: DeepReadonly) { return (

- {state.wordsLeft.map((n, team) => { + {wordsLeft.map((n, team) => { return ( {team !== 0 ? - : null} {n} @@ -160,21 +182,22 @@ const Header = ({ send, state, pState, pTeam }: GameViewProps) => {

- +
); -}; +}, +isEqual); const sliderMarks = range(30, 301, 30).map((v) => ({ value: v })); @@ -333,53 +356,22 @@ const ChangeNicknameButton = ({ send }: { send: Sender }) => { ); }; -const useSidebarStyles = makeStyles((_theme: Theme) => - createStyles({ - dropzone: { - backgroundColor: 'initial', - }, - previewGrid: { - width: '100%', - }, - }) -); - -interface SidebarProps { +interface SidebarTeamsProps { send: Sender; teams: StateTeams; - lists: StateWordList[]; pTeam: number; playerID: string; - version: number; - timer: StateTimer | undefined | null; } -const Sidebar = React.memo(function Sidebar({ +const SidebarTeams = React.memo(function SidebarTeams({ send, teams, - lists, pTeam, playerID, - version, - timer, -}: DeepReadonly) { - const classes = useSidebarStyles(); +}: DeepReadonly) { const theme = useTheme(); const nameShade = theme.palette.type === 'dark' ? 400 : 600; - const wordCount = React.useMemo( - () => - lists.reduce((curr, l) => { - if (l.enabled) { - return curr + l.count; - } - return curr; - }, 0), - [lists] - ); - - const [uploadOpen, setUploadOpen] = React.useState(false); - return ( <>

Teams

@@ -436,7 +428,45 @@ const Sidebar = React.memo(function Sidebar({ + + ); +}, +isEqual); +const useSidebarPacksStyles = makeStyles((_theme: Theme) => + createStyles({ + dropzone: { + backgroundColor: 'initial', + }, + previewGrid: { + width: '100%', + }, + }) +); + +interface SidebarPacksProps { + send: Sender; + lists: StateWordList[]; +} + +const SidebarPacks = React.memo(function SidebarPacks({ send, lists }: DeepReadonly) { + const classes = useSidebarPacksStyles(); + + const wordCount = React.useMemo( + () => + lists.reduce((curr, l) => { + if (l.enabled) { + return curr + l.count; + } + return curr; + }, 0), + [lists] + ); + + const [uploadOpen, setUploadOpen] = React.useState(false); + + return ( + <>

Packs

{wordCount} words in the selected packs.

@@ -508,6 +538,25 @@ const Sidebar = React.memo(function Sidebar({ )}
+ + ); +}, isEqual); + +interface SidebarProps { + send: Sender; + teams: StateTeams; + lists: StateWordList[]; + pTeam: number; + playerID: string; + version: number; + timer: StateTimer | undefined | null; +} + +const Sidebar = ({ send, teams, lists, pTeam, playerID, version, timer }: DeepReadonly) => { + return ( + <> + + {!isDefined(timer) ? null : (
@@ -515,21 +564,6 @@ const Sidebar = React.memo(function Sidebar({ )} ); -}, -isEqual); - -const Board2 = ({ send, state, pState, pTeam }: GameViewProps) => { - const myTurn = state.turn === pTeam; - - return ( - - ); }; const useFooterStyles = makeStyles((_theme: Theme) => @@ -560,7 +594,7 @@ interface FooterProps { hasTimer: boolean; } -const Footer = React.memo(function Footer({ send, end, spymaster, hideBomb, hasTimer }: FooterProps) { +const Footer = React.memo(function Footer({ send, end, spymaster, hideBomb, hasTimer }: DeepReadonly) { const classes = useFooterStyles(); return ( @@ -636,6 +670,39 @@ const Footer = React.memo(function Footer({ send, end, spymaster, hideBomb, hasT ); }, isEqual); +const useCornerButtonsStyle = makeStyles((_theme: Theme) => + createStyles({ + wrapper: { + position: 'absolute', + top: 0, + left: 0, + margin: '0.5rem', + }, + button: { + marginRight: '0.5rem', + }, + }) +); + +const CornerButtons = React.memo(function CornerButtons({ roomID, leave }: { roomID: string; leave: () => void }) { + const classes = useCornerButtonsStyle(); + + return ( + <> +
+ + } + /> +
+ + ); +}); + const useStyles = makeStyles((theme: Theme) => createStyles({ root: { @@ -675,15 +742,6 @@ const useStyles = makeStyles((theme: Theme) => sidebar: { gridArea: 'sidebar', }, - leaveWrapper: { - position: 'absolute', - top: 0, - left: 0, - margin: '0.5rem', - }, - leaveButton: { - marginRight: '0.5rem', - }, }) ); @@ -696,47 +754,53 @@ export interface GameViewProps { pTeam: number; } -export const GameView = (props: DeepReadonly) => { +export const GameView = ({ roomID, leave, send, state, pState, pTeam }: DeepReadonly) => { const classes = useStyles(); - const end = isDefined(props.state.winner); + const end = isDefined(state.winner); + const myTurn = state.turn === pTeam; return (
-
- - } - /> -
+
-
+
- +