From 47a0551967ca420a957e2123d56bd7f0c8a95c53 Mon Sep 17 00:00:00 2001 From: Johnny A <5891646+johnny243@users.noreply.github.com> Date: Thu, 30 Jun 2022 17:21:48 -0400 Subject: [PATCH] fix: debounce saving task description/draft (#1187) Co-authored-by: Johnny Almonte --- .../src/app/hooks.ts | 12 +++++++++++- .../src/features/tasks/CreateTask.tsx | 12 ++++++++---- .../src/features/tasks/TaskItem.tsx | 19 ++++++------------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/app/hooks.ts b/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/app/hooks.ts index 1f2d4a513..bad2dfc77 100644 --- a/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/app/hooks.ts +++ b/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/app/hooks.ts @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' import useResizeObserver from '@react-hook/resize-observer' import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' import type { AppDispatch, RootState } from './store' @@ -32,3 +32,13 @@ export const useResize = (ref: React.RefObject, effect: (target: HT } }) } + +export const useDebouncedCallback = (callback: () => void, waitMs: number = 500) => { + const timeout = useRef() + + clearTimeout(timeout.current) + + timeout.current = setTimeout(() => { + callback() + }, waitMs) +} diff --git a/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/features/tasks/CreateTask.tsx b/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/features/tasks/CreateTask.tsx index a8783c053..f61ce1a68 100644 --- a/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/features/tasks/CreateTask.tsx +++ b/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/features/tasks/CreateTask.tsx @@ -2,7 +2,7 @@ import { ChangeEvent, createRef, KeyboardEvent, useState } from 'react' import styled from 'styled-components' import { v4 as uuidv4 } from 'uuid' -import { useAppDispatch, useAppSelector } from '../../app/hooks' +import { useAppDispatch, useAppSelector, useDebouncedCallback } from '../../app/hooks' import { GroupModel, taskAdded, tasksGroupDraft } from './tasks-slice' import { TextInput } from '../../common/components' @@ -37,9 +37,7 @@ const CreateTask: React.FC = ({ group }) => { const [taskDraft, setTaskDraft] = useState(group.draft ?? '') function onTextChange(event: ChangeEvent) { - const draft = event.target.value - dispatch(tasksGroupDraft({ groupName, draft })) - setTaskDraft(draft) + setTaskDraft(event.target.value) } function handleKeyPress(event: KeyboardEvent) { @@ -54,6 +52,12 @@ const CreateTask: React.FC = ({ group }) => { } } + useDebouncedCallback(() => { + if (group.draft !== undefined && taskDraft !== group.draft) { + dispatch(tasksGroupDraft({ groupName, draft: taskDraft })) + } + }) + if (!canEdit) { return <> } diff --git a/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/features/tasks/TaskItem.tsx b/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/features/tasks/TaskItem.tsx index 910085ebd..5ef92bd74 100644 --- a/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/features/tasks/TaskItem.tsx +++ b/packages/components/src/Packages/Editors/org.standardnotes.advanced-checklist/src/features/tasks/TaskItem.tsx @@ -3,7 +3,7 @@ import './TaskItem.scss' import { ChangeEvent, createRef, KeyboardEvent, useState } from 'react' import styled from 'styled-components' -import { useAppDispatch, useAppSelector, useDidMount, useResize } from '../../app/hooks' +import { useAppDispatch, useAppSelector, useDebouncedCallback, useResize } from '../../app/hooks' import { taskDeleted, TaskModel, taskModified, taskToggled } from './tasks-slice' import { CheckBoxInput, TextAreaInput } from '../../common/components' @@ -116,18 +116,11 @@ const TaskItem: React.FC = ({ task, groupName, innerRef, ...props } } - /** - * Save the task after the user has stopped typing. - */ - useDidMount(() => { - const timeoutId = setTimeout(() => { - if (description !== task.description) { - dispatch(taskModified({ task: { id: task.id, description }, groupName })) - } - }, 500) - - return () => clearTimeout(timeoutId) - }, [description, groupName]) + useDebouncedCallback(() => { + if (description !== task.description) { + dispatch(taskModified({ task: { id: task.id, description }, groupName })) + } + }) useResize(textAreaRef, resizeTextArea)