Skip to content

Commit

Permalink
fix: memoize requirements in Screen components with custom hook
Browse files Browse the repository at this point in the history
  • Loading branch information
knipec committed Dec 19, 2024
1 parent bbdec4c commit de5fd9a
Show file tree
Hide file tree
Showing 28 changed files with 202 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/

import {useEffect} from 'react';
import {useEffect, useMemo} from 'react';

type Requirement = {
data: any;
Expand Down Expand Up @@ -56,9 +56,24 @@ type Props = {
*/
export const ScreenDataRequirements = ({requirements, children}: Props) => {
const requiredDataExists = useRequiredData(requirements);

if (!requiredDataExists) {
return null;
}
return <>{children()}</>;
};

/*
* I believe this is not strictly necessary; if a screen is re-rendering, the ScreenDataRequirements component
* will re-render regardless of if its props change (unless memoized)
*/
export const useMemoizedRequirements = (
requirementsAsNewObj: Requirement[],
) => {
const deps = requirementsAsNewObj.flatMap(r => [r.data, r.doIfMissing]);
return useMemo(() => {
return requirementsAsNewObj;
// The linter doesn't like the dynamic dependency list, but the useMemo should only depend on the values of the required data
// and missing data handlers. If it depends on the list object, it's re-created every render.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ import {
useNavToBottomTabsAndShowSyncError,
usePopNavigationAndShowSyncError,
} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
Box,
Column,
Expand Down Expand Up @@ -76,10 +79,10 @@ export const AddUserToProjectRoleScreen = ({projectId, userId}: Props) => {

const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const handleMissingUser = usePopNavigationAndShowSyncError();
const requirements = [
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
{data: user, doIfMissing: handleMissingUser},
];
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import {useTranslation} from 'react-i18next';

import {ScreenContentSection} from 'terraso-mobile-client/components/content/ScreenContentSection';
import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {Box, Text} from 'terraso-mobile-client/components/NativeBaseAdapters';
import {AppBar} from 'terraso-mobile-client/navigation/components/AppBar';
import {AddTeamMemberForm} from 'terraso-mobile-client/screens/AddUserToProjectScreen/components/AddTeamMemberForm';
Expand All @@ -41,7 +44,9 @@ export const AddUserToProjectScreen = ({projectId}: Props) => {
// wanting to add multiple users at the same time.

const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: project, doIfMissing: handleMissingProject}];
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
9 changes: 7 additions & 2 deletions dev-client/src/screens/EditPinnedNoteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import {Keyboard} from 'react-native';
import {ProjectUpdateMutationInput} from 'terraso-client-shared/graphqlSchema/graphql';

import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
Box,
Column,
Expand Down Expand Up @@ -70,7 +73,9 @@ export const EditPinnedNoteScreen = ({projectId}: Props) => {
};

const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: project, doIfMissing: handleMissingProject}];
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
import {Coords} from 'terraso-client-shared/types';

import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {LocationDashboardContent} from 'terraso-mobile-client/screens/LocationScreens/LocationDashboardContent';
import {useSelector} from 'terraso-mobile-client/store';
import {selectSite} from 'terraso-mobile-client/store/selectors';
Expand All @@ -30,7 +33,9 @@ export const SiteDashboardScreen = ({siteId}: Props) => {
const site = useSelector(selectSite(siteId));

const handleMissingSite = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: site, doIfMissing: handleMissingSite}];
const requirements = useMemoizedRequirements([
{data: site, doIfMissing: handleMissingSite},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import {ScrollView} from 'react-native-gesture-handler';
import {Coords} from 'terraso-client-shared/types';

import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {SiteRoleContextProvider} from 'terraso-mobile-client/context/SiteRoleContext';
import {AppBar} from 'terraso-mobile-client/navigation/components/AppBar';
import {SiteDataSection} from 'terraso-mobile-client/screens/LocationScreens/components/soilId/SiteDataSection';
Expand All @@ -43,7 +46,9 @@ export const SiteLocationSoilIdScreen = ({siteId, coords}: SiteProps) => {
const site = useSelector(state => selectSite(siteId)(state));

const handleMissingSite = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: site, doIfMissing: handleMissingSite}];
const requirements = useMemoizedRequirements([
{data: site, doIfMissing: handleMissingSite},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
9 changes: 7 additions & 2 deletions dev-client/src/screens/LocationScreens/SiteTabsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import {useTranslation} from 'react-i18next';

import {AppBarIconButton} from 'terraso-mobile-client/components/buttons/icons/appBar/AppBarIconButton';
import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {SiteRoleContextProvider} from 'terraso-mobile-client/context/SiteRoleContext';
import {isSiteManager} from 'terraso-mobile-client/model/permissions/permissions';
import {AppBar} from 'terraso-mobile-client/navigation/components/AppBar';
Expand Down Expand Up @@ -52,7 +55,9 @@ export const SiteTabsScreen = (props: Props) => {
const userRole = useSelector(state => selectUserRoleSite(state, siteId));

const handleMissingSite = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: site, doIfMissing: handleMissingSite}];
const requirements = useMemoizedRequirements([
{data: site, doIfMissing: handleMissingSite},
]);

const appBarRightButton = useMemo(() => {
// display nothing if user does not own the site / is not manager
Expand Down
9 changes: 6 additions & 3 deletions dev-client/src/screens/ManageTeamMemberScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ import {
useNavToBottomTabsAndShowSyncError,
usePopNavigationAndShowSyncError,
} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {Icon} from 'terraso-mobile-client/components/icons/Icon';
import {ConfirmModal} from 'terraso-mobile-client/components/modals/ConfirmModal';
import {
Expand Down Expand Up @@ -88,10 +91,10 @@ export const ManageTeamMemberScreen = ({

const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const handleMissingUser = usePopNavigationAndShowSyncError();
const requirements = [
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
{data: user, doIfMissing: handleMissingUser},
];
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ import {Accordion} from 'terraso-mobile-client/components/Accordion';
import {HelpContentSpacer} from 'terraso-mobile-client/components/content/HelpContentSpacer';
import {DataPrivacyInfoButton} from 'terraso-mobile-client/components/content/info/privacy/DataPrivacyInfoButton';
import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {Icon} from 'terraso-mobile-client/components/icons/Icon';
import {
Box,
Expand Down Expand Up @@ -83,7 +86,9 @@ export const ProjectInputScreen = ({
const allowEditing = useMemo(() => userRole === 'MANAGER', [userRole]);

const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: project, doIfMissing: handleMissingProject}];
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
9 changes: 7 additions & 2 deletions dev-client/src/screens/ProjectSettingsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import {ProjectUpdateMutationInput} from 'terraso-client-shared/graphqlSchema/gr

import DeleteButton from 'terraso-mobile-client/components/buttons/DeleteButton';
import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {ConfirmModal} from 'terraso-mobile-client/components/modals/ConfirmModal';
import {Column} from 'terraso-mobile-client/components/NativeBaseAdapters';
import {RestrictByProjectRole} from 'terraso-mobile-client/components/restrictions/RestrictByRole';
Expand Down Expand Up @@ -69,7 +72,9 @@ export function ProjectSettingsScreen({
const userRole = useProjectRoleContext();

const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: project, doIfMissing: handleMissingProject}];
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
9 changes: 7 additions & 2 deletions dev-client/src/screens/ProjectSitesScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ import {normalizeText} from 'terraso-client-shared/utils';

import {IconButton} from 'terraso-mobile-client/components/buttons/icons/IconButton';
import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ListFilterModal,
ListFilterProvider,
Expand Down Expand Up @@ -264,7 +267,9 @@ export function ProjectSitesScreen({

const project = useSelector(selectProject(projectId));
const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: project, doIfMissing: handleMissingProject}];
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import {ProjectMembership} from 'terraso-client-shared/project/projectTypes';

import {AddButton} from 'terraso-mobile-client/components/AddButton';
import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
Box,
Column,
Expand Down Expand Up @@ -96,7 +99,9 @@ export const ProjectTeamScreen = ({route}: Props) => {

const project = useSelector(selectProject(route.params.projectId));
const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: project, doIfMissing: handleMissingProject}];
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
9 changes: 7 additions & 2 deletions dev-client/src/screens/ProjectViewScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
*/

import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {ProjectRoleContextProvider} from 'terraso-mobile-client/context/ProjectRoleContext';
import {AppBar} from 'terraso-mobile-client/navigation/components/AppBar';
import {ProjectTabNavigator} from 'terraso-mobile-client/navigation/navigators/ProjectTabNavigator';
Expand All @@ -29,7 +32,9 @@ export const ProjectViewScreen = ({projectId}: Props) => {
const project = useSelector(state => state.project.projects[projectId]);
const handleMissingProject = useNavToBottomTabsAndShowSyncError();

const requirements = [{data: project, doIfMissing: handleMissingProject}];
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
9 changes: 7 additions & 2 deletions dev-client/src/screens/SiteNotesScreen/AddSiteNoteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import {Keyboard} from 'react-native';
import {SiteNoteAddMutationInput} from 'terraso-client-shared/graphqlSchema/graphql';

import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
Box,
Column,
Expand Down Expand Up @@ -72,7 +75,9 @@ export const AddSiteNoteScreen = ({siteId}: Props) => {

const site = useSelector(selectSite(siteId));
const handleMissingSite = useNavToBottomTabsAndShowSyncError();
const requirements = [{data: site, doIfMissing: handleMissingSite}];
const requirements = useMemoizedRequirements([
{data: site, doIfMissing: handleMissingSite},
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
9 changes: 6 additions & 3 deletions dev-client/src/screens/SiteNotesScreen/EditSiteNoteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
import {useCallback} from 'react';

import {useNavToBottomTabsAndShowSyncError} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {isFlagEnabled} from 'terraso-mobile-client/config/featureFlags';
import {useSyncNotificationContext} from 'terraso-mobile-client/context/SyncNotificationContext';
import {useNavigation} from 'terraso-mobile-client/navigation/hooks/useNavigation';
Expand Down Expand Up @@ -50,10 +53,10 @@ export const EditSiteNoteScreen = ({noteId, siteId}: Props) => {
syncNotifications.showError();
}
}, [navigation, siteId, syncNotifications]);
const requirements = [
const requirements = useMemoizedRequirements([
{data: site, doIfMissing: handleMissingSite},
{data: note, doIfMissing: handleMissingSiteNote},
];
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import {
useNavToBottomTabsAndShowSyncError,
usePopNavigationAndShowSyncError,
} from 'terraso-mobile-client/components/dataRequirements/handleMissingData';
import {ScreenDataRequirements} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
ScreenDataRequirements,
useMemoizedRequirements,
} from 'terraso-mobile-client/components/dataRequirements/ScreenDataRequirements';
import {
Column,
Heading,
Expand Down Expand Up @@ -52,10 +55,10 @@ export const ReadPinnedNoteScreen = ({projectId}: Props) => {

const handleMissingProject = useNavToBottomTabsAndShowSyncError();
const handleMissingPinnedNote = usePopNavigationAndShowSyncError();
const requirements = [
const requirements = useMemoizedRequirements([
{data: project, doIfMissing: handleMissingProject},
{data: content, doIfMissing: handleMissingPinnedNote},
];
]);

return (
<ScreenDataRequirements requirements={requirements}>
Expand Down
Loading

0 comments on commit de5fd9a

Please sign in to comment.