From 791023b5c0c17e2da998c160950c481e3c2d58c6 Mon Sep 17 00:00:00 2001 From: Nithin Date: Sun, 28 Feb 2021 18:58:23 +0530 Subject: [PATCH] Moved token and getUserQueues selectors to prevent useless side effects (#556) * Moved token selector to tokenlist * Moved getUserQueues dispatch to LandingPage to prevent unneeded popup on other page loads * Removed console.log * Moved getUserQueues back to Layout and changes the popup behaviour * Changed anchor tag redirects to use react router history * Add comments to layout * Fix code style issues with Prettier * Made utility function for delayed scrolling Co-authored-by: daltonfury42 Co-authored-by: Lint Action --- simplq/src/components/Layout/Layout.jsx | 12 +++++------ .../common/ClickableLogo/ClickableLogo.jsx | 3 +-- simplq/src/components/common/Nav/LeftNav.jsx | 16 +++++++++++--- simplq/src/components/common/Nav/Navbar.jsx | 3 +-- .../src/components/pages/Admin/AdminPage.jsx | 6 ++---- .../src/components/pages/Admin/TokenList.jsx | 9 +++++--- .../src/components/pages/Home/LandingPage.jsx | 1 + simplq/src/components/pages/Home/MyQueues.jsx | 9 +++++++- simplq/src/store/appSlice.js | 11 +--------- simplq/src/utils/scrollingOperations.js | 21 +++++++++++++++++-- 10 files changed, 58 insertions(+), 33 deletions(-) diff --git a/simplq/src/components/Layout/Layout.jsx b/simplq/src/components/Layout/Layout.jsx index bde01a0f..1de535c2 100644 --- a/simplq/src/components/Layout/Layout.jsx +++ b/simplq/src/components/Layout/Layout.jsx @@ -1,9 +1,9 @@ import React, { useEffect } from 'react'; +import { useGetUserQueues } from 'store/asyncActions'; +import { useDispatch } from 'react-redux'; import { useAuth0 } from '@auth0/auth0-react'; import Footer from 'components/common/Footer'; import Loading from 'components/common/Loading/Loading'; -import { useGetUserQueues } from 'store/asyncActions'; -import { useDispatch } from 'react-redux'; import Routes from './Routes'; import styles from './Layout.module.scss'; @@ -13,8 +13,8 @@ function Layout() { const getUserQueues = useGetUserQueues(); useEffect(() => { - // TODO: Server still returns queues for anonymous users - // Dispatch action only if auth is loaded + // All the backend API calls that should happen at the start goes here. + // They will the dispached as soon as Auth0 has initilised. if (isLoading === false) { dispatch(getUserQueues()); } @@ -23,8 +23,8 @@ function Layout() { return (
- {/* TODO: Since we have better way for managing loading status - remove conditional loading of the layout once it is handled elswhere */} + {/* We load the main app content only after Auth0 has been initilised. + This helps ensure that no backend API calls are made before auth the initilisation */} diff --git a/simplq/src/components/common/ClickableLogo/ClickableLogo.jsx b/simplq/src/components/common/ClickableLogo/ClickableLogo.jsx index c299799e..4106b381 100644 --- a/simplq/src/components/common/ClickableLogo/ClickableLogo.jsx +++ b/simplq/src/components/common/ClickableLogo/ClickableLogo.jsx @@ -8,8 +8,7 @@ import styles from './ClickableLogo.module.scss'; export default (props) => { const history = useHistory(); const defaultOnClick = () => { - history.push('/'); - smoothScrollToHomePageTop(); + smoothScrollToHomePageTop(history); }; return (
diff --git a/simplq/src/components/common/Nav/LeftNav.jsx b/simplq/src/components/common/Nav/LeftNav.jsx index de72e132..89e74975 100644 --- a/simplq/src/components/common/Nav/LeftNav.jsx +++ b/simplq/src/components/common/Nav/LeftNav.jsx @@ -1,11 +1,14 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ import React from 'react'; -import { smoothScrollTo } from 'utils/scrollingOperations'; +import { smoothScrollTo, smoothScrollToHomePageTop, onLoadById } from 'utils/scrollingOperations'; +import { useHistory } from 'react-router'; import styles from './Nav.module.scss'; import LoginButton from '../LoginButton'; const LeftNav = ({ open, toggleClose }) => { + const history = useHistory(); + const scrollToHowItWorks = () => { // Close the navbar on click toggleClose(); @@ -15,14 +18,21 @@ const LeftNav = ({ open, toggleClose }) => { // element is on the current page, just have to scroll to it smoothScrollTo(element); } else { - window.location.href = '/#target_how_it_works'; + history.push('/'); + // wait till page loads before getting element + onLoadById('target_how_it_works', smoothScrollTo); } }; return (
  • - + smoothScrollToHomePageTop(history)} + onClick={() => smoothScrollToHomePageTop(history)} + > Home
  • diff --git a/simplq/src/components/common/Nav/Navbar.jsx b/simplq/src/components/common/Nav/Navbar.jsx index 04b21ae2..67300e0c 100644 --- a/simplq/src/components/common/Nav/Navbar.jsx +++ b/simplq/src/components/common/Nav/Navbar.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import { smoothScrollToHomePageTop } from 'utils/scrollingOperations'; import styles from './Nav.module.scss'; import Burger from './Burger'; import Logo from '../ClickableLogo'; @@ -7,7 +6,7 @@ import Logo from '../ClickableLogo'; export const Navbar = () => { return ( ); diff --git a/simplq/src/components/pages/Admin/AdminPage.jsx b/simplq/src/components/pages/Admin/AdminPage.jsx index 2ed5f7a2..873e059e 100644 --- a/simplq/src/components/pages/Admin/AdminPage.jsx +++ b/simplq/src/components/pages/Admin/AdminPage.jsx @@ -3,7 +3,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useAuth0 } from '@auth0/auth0-react'; import { useDispatch, useSelector } from 'react-redux'; -import { selectTokens, selectQueueName } from 'store/selectedQueue'; +import { selectQueueName } from 'store/selectedQueue'; import Ribbon from 'components/common/Ribbon'; import Tour from 'components/common/Tour'; import { useGetSelectedQueue } from 'store/asyncActions'; @@ -19,14 +19,12 @@ let timeoutId; export default (props) => { const queueId = props.match.params.queueId; const queueName = useSelector(selectQueueName); - const tokens = useSelector(selectTokens); const description = queueName && 'Ready to share'; const dispatch = useDispatch(); const getSelectedQueue = useGetSelectedQueue(); const [toursteps, setToursteps] = useState(getToursteps(window.innerHeight)); const { isAuthenticated } = useAuth0(); - const update = useCallback(() => { clearTimeout(timeoutId); dispatch(getSelectedQueue({ queueId })); @@ -58,7 +56,7 @@ export default (props) => { /> )}
    - +
diff --git a/simplq/src/components/pages/Admin/TokenList.jsx b/simplq/src/components/pages/Admin/TokenList.jsx index 1ed73e15..85f49830 100644 --- a/simplq/src/components/pages/Admin/TokenList.jsx +++ b/simplq/src/components/pages/Admin/TokenList.jsx @@ -1,10 +1,13 @@ import React from 'react'; import Loading from 'components/common/Loading/Loading'; +import { useSelector } from 'react-redux'; +import { selectTokens } from 'store/selectedQueue'; import Token from './Token'; import styles from './admin.module.scss'; -function TokenList({ tokens }) { - const Dispaly = () => +function TokenList() { + const tokens = useSelector(selectTokens); + const ListContent = () => tokens.length === 0 ? (

Your queue has been created and is currently empty. Waiting for people to join...

) : ( @@ -14,7 +17,7 @@ function TokenList({ tokens }) { return (
- +
); diff --git a/simplq/src/components/pages/Home/LandingPage.jsx b/simplq/src/components/pages/Home/LandingPage.jsx index 05cf4bce..62a5e80b 100644 --- a/simplq/src/components/pages/Home/LandingPage.jsx +++ b/simplq/src/components/pages/Home/LandingPage.jsx @@ -11,6 +11,7 @@ export default () => { if (isAuthenticated) { subtitle = `Hi ${user.name}, welcome back!`; } + return (
diff --git a/simplq/src/components/pages/Home/MyQueues.jsx b/simplq/src/components/pages/Home/MyQueues.jsx index 9d544364..baa04e6f 100644 --- a/simplq/src/components/pages/Home/MyQueues.jsx +++ b/simplq/src/components/pages/Home/MyQueues.jsx @@ -1,10 +1,11 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import DeleteIcon from '@material-ui/icons/Delete'; import IconButton from '@material-ui/core/IconButton'; import { useHistory } from 'react-router'; import { useDeleteQueue } from 'store/asyncActions'; import { selectQueues } from 'store/queues'; import { useDispatch, useSelector } from 'react-redux'; +import { setInfoPopupMessage } from 'store/appSlice'; import styles from './Home.module.scss'; export default () => { @@ -13,6 +14,12 @@ export default () => { const queues = useSelector(selectQueues); const deleteQueue = useDeleteQueue(); + useEffect(() => { + if (queues) { + dispatch(setInfoPopupMessage(`Number of queues fetched: ${queues.length}`)); + } + }, [dispatch, queues]); + const handleDelete = (e, queue) => { // Don't trigger parent's onClick e.stopPropagation(); diff --git a/simplq/src/store/appSlice.js b/simplq/src/store/appSlice.js index 923f0141..326ff9d0 100644 --- a/simplq/src/store/appSlice.js +++ b/simplq/src/store/appSlice.js @@ -1,6 +1,6 @@ /* eslint-disable no-param-reassign */ import { createSlice } from '@reduxjs/toolkit'; -import { getUserQueues, deleteQueue, getQueueStatusByName, joinQueue } from 'store/asyncActions'; +import { deleteQueue, getQueueStatusByName, joinQueue } from 'store/asyncActions'; const appSlice = createSlice({ name: 'appSlice', @@ -21,15 +21,6 @@ const appSlice = createSlice({ }, }, extraReducers: { - [getUserQueues.pending]: (state) => { - state.infoText = `Loading queues...`; - }, - [getUserQueues.rejected]: (state, action) => { - state.errorText = action.error.message; - }, - [getUserQueues.fulfilled]: (state, action) => { - state.infoText = `Number of queues fetched: ${action.payload.queues.length}`; - }, [deleteQueue.pending]: (state) => { state.infoText = `Deleting queue...`; }, diff --git a/simplq/src/utils/scrollingOperations.js b/simplq/src/utils/scrollingOperations.js index a70a5d4c..e75d0f1b 100644 --- a/simplq/src/utils/scrollingOperations.js +++ b/simplq/src/utils/scrollingOperations.js @@ -13,11 +13,28 @@ export const smoothScrollTo = (targetElement) => { }); }; -export const smoothScrollToHomePageTop = () => { +export const smoothScrollToHomePageTop = (history) => { const element = document.getElementById('target_top'); if (element) { smoothScrollTo(element); } else { - window.location.href = '/'; + history.push('/'); } }; + +/** + * Execute a callback as soon as an element is available on the DOM. + * + * id - element id to wait on + * callback - callback to execute as soon as the element becomes available. The + * element is passed to the callback and it is triggered. + * */ +export const onLoadById = (id, callback) => { + const checkAndExecute = setInterval(() => { + const element = document.getElementById(id); + if (element) { + callback(element); + clearInterval(checkAndExecute); + } + }, 100); +};