Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use targeted useAppSelector to avoid sidebar rerender loop #2834

Merged
merged 2 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,25 @@ import {
flagWord,
setVern,
} from "goals/MergeDuplicates/Redux/MergeDupsActions";
import { MergeTreeState } from "goals/MergeDuplicates/Redux/MergeDupsReduxTypes";
import { useAppDispatch } from "types/hooks";
import { StoreState } from "types";
import { useAppDispatch, useAppSelector } from "types/hooks";
import theme from "types/theme";
import { TypographyWithFont } from "utilities/fontComponents";

interface DropWordProps {
mergeState: MergeTreeState;
wordId: string;
}

export default function DropWord(props: DropWordProps): ReactElement {
const dispatch = useAppDispatch();
const data = useAppSelector(
(state: StoreState) => state.mergeDuplicateGoal.data
);
const treeWord = useAppSelector(
(state: StoreState) => state.mergeDuplicateGoal.tree.words[props.wordId]
);
const { t } = useTranslation();

const treeWord = props.mergeState.tree.words[props.wordId];
const data = props.mergeState.data;
let protectedWithOneChild = false;
const verns: string[] = [];
if (treeWord) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,30 @@ import SenseCardContent from "goals/MergeDuplicates/MergeDupsStep/SenseCardConte
import {
MergeTreeReference,
MergeTreeSense,
Sidebar,
} from "goals/MergeDuplicates/MergeDupsTreeTypes";
import { StoreState } from "types";
import { useAppSelector } from "types/hooks";
import theme from "types/theme";

interface SidebarDragSenseProps {
sidebar: Sidebar;
sense: MergeTreeSense;
index: number;
}

export default function SidebarDragSense(
props: SidebarDragSenseProps
): ReactElement {
const ref: MergeTreeReference = {
wordId: props.sidebar.wordId,
mergeSenseId: props.sidebar.mergeSenseId,
order: props.index,
};
const draggableId = useAppSelector((state: StoreState) => {
const { mergeSenseId, wordId } = state.mergeDuplicateGoal.tree.sidebar;
const order = props.index;
const ref: MergeTreeReference = { wordId, mergeSenseId, order };
return JSON.stringify(ref);
});

return (
<Draggable
key={props.sense.guid}
draggableId={JSON.stringify(ref)}
draggableId={draggableId}
index={props.index}
isDragDisabled={props.sense.protected}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ import { ReactElement } from "react";
import { Droppable } from "react-beautiful-dnd";

import SidebarDragSense from "goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/SidebarDragSense";
import {
MergeTreeSense,
Sidebar,
} from "goals/MergeDuplicates/MergeDupsTreeTypes";
import { MergeTreeSense } from "goals/MergeDuplicates/MergeDupsTreeTypes";
import { setSidebar } from "goals/MergeDuplicates/Redux/MergeDupsActions";
import { useAppDispatch } from "types/hooks";
import { StoreState } from "types";
import { useAppDispatch, useAppSelector } from "types/hooks";

interface SidebarDropProps {
sidebar: Sidebar;
vernacular: string;
}

export default function SidebarDrop(props: SidebarDropProps): ReactElement {
export default function SidebarDrop(): ReactElement {
const dispatch = useAppDispatch();
const sidebar = useAppSelector(
(state: StoreState) => state.mergeDuplicateGoal.tree.sidebar
);
const vernacular = useAppSelector((state: StoreState) => {
const tree = state.mergeDuplicateGoal.tree;
return tree.words[tree.sidebar.wordId]?.vern;
});

return (
<Droppable
droppableId={`${props.sidebar.wordId} ${props.sidebar.mergeSenseId}`}
key={props.sidebar.mergeSenseId}
droppableId={`${sidebar.wordId} ${sidebar.mergeSenseId}`}
key={sidebar.mergeSenseId}
>
{(providedDroppable): ReactElement => (
<div
Expand All @@ -37,14 +37,9 @@ export default function SidebarDrop(props: SidebarDropProps): ReactElement {
>
<ArrowForwardIos />
</IconButton>
<Typography variant="h5">{props.vernacular}</Typography>
{props.sidebar.senses.map((sense: MergeTreeSense, index: number) => (
<SidebarDragSense
key={index}
index={index}
sidebar={props.sidebar}
sense={sense}
/>
<Typography variant="h5">{vernacular}</Typography>
{sidebar.senses.map((sense: MergeTreeSense, index: number) => (
<SidebarDragSense key={index} index={index} sense={sense} />
))}
{providedDroppable.placeholder}
</div>
Expand Down
44 changes: 22 additions & 22 deletions src/goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,25 @@ export const trashId = "trash-drop";

export default function MergeDragDrop(): ReactElement {
const dispatch = useAppDispatch();
const mergeState = useAppSelector(
(state: StoreState) => state.mergeDuplicateGoal
const sidebarOpen = useAppSelector(
(state: StoreState) =>
state.mergeDuplicateGoal.tree.sidebar.senses.length > 1
);
const sidebarProtected = useAppSelector((state: StoreState) => {
const senses = state.mergeDuplicateGoal.tree.sidebar.senses;
return senses.length && senses[0].protected;
});
const words = useAppSelector(
(state: StoreState) => state.mergeDuplicateGoal.tree.words
);

const [senseToDelete, setSenseToDelete] = useState<string>("");
const { t } = useTranslation();

const sidebar = mergeState.tree.sidebar;
const treeWords = mergeState.tree.words;

function handleDrop(res: DropResult): void {
const src: MergeTreeReference = JSON.parse(res.draggableId);
const srcWordId = res.source.droppableId;
const srcWord = treeWords[srcWordId];
const srcWord = words[srcWordId];
if (srcWord?.protected && Object.keys(srcWord.sensesGuids).length === 1) {
// Case 0: The final sense of a protected word cannot be moved.
return;
Expand Down Expand Up @@ -89,9 +95,7 @@ export default function MergeDragDrop(): ReactElement {
const destOrder = res.destination.index;
if (
src.order === destOrder ||
(destOrder === 0 &&
src.order !== undefined &&
sidebar.senses[0].protected)
(destOrder === 0 && src.order !== undefined && sidebarProtected)
) {
// If the sense wasn't moved or was moved within the sidebar above a protected sense, do nothing.
return;
Expand All @@ -107,31 +111,27 @@ export default function MergeDragDrop(): ReactElement {
}

function renderSidebar(): ReactElement {
if (sidebar.senses.length <= 1) {
return <div />;
}
return (
return sidebarOpen ? (
<Drawer
anchor="right"
variant="persistent"
open={sidebar.senses.length > 1}
open={sidebarOpen}
SlideProps={{
style: {
height: `calc(100% - ${appBarHeight}px)`,
top: appBarHeight,
},
}}
>
<SidebarDrop
sidebar={sidebar}
vernacular={treeWords[sidebar.wordId]?.vern}
/>
<SidebarDrop />
</Drawer>
) : (
<div />
);
}

const newId = v4();
const colCount = Object.keys(treeWords).length + 1; // +1 for extra empty word.
const colCount = Object.keys(words).length + 1; // +1 for extra empty word.

// This prevents things from moving when a draggable is dragged over the trash.
const trashPlaceholderStyle: CSSProperties = {
Expand All @@ -157,16 +157,16 @@ export default function MergeDragDrop(): ReactElement {
</Grid>
<Grid item sm={11} xs={10 /* Allow trash icon more space. */}>
<ImageList rowHeight="auto" cols={colCount} style={{ width: "90vw" }}>
{Object.keys(treeWords).map((key) => (
{Object.keys(words).map((key) => (
<ImageListItem
key={key}
style={{ height: "70vh", margin: theme.spacing(1) }}
>
<DropWord mergeState={mergeState} wordId={key} />
<DropWord wordId={key} />
</ImageListItem>
))}
<ImageListItem key={newId} style={{ margin: theme.spacing(1) }}>
<DropWord mergeState={mergeState} wordId={newId} />
<DropWord wordId={newId} />
</ImageListItem>
{renderSidebar()}
<CancelConfirmDialog
Expand Down