From 96884372b4e00f76f0269db1882389e6794c32f8 Mon Sep 17 00:00:00 2001 From: Dominik Pschenitschni Date: Wed, 17 Jul 2024 17:17:35 +0200 Subject: [PATCH] fix(projects): trigger only single mutation Previously these store methods created multiple edits on deep objects in the store or edited a deep nested object directly. This is bad because: - multiple edits lead to multiple triggers of all the watchers on the project. - in theory we should listen deep to a project if we use some deep reactive value of a project, if we want deep updates. Because this is easy to forget, it's better to update the project directly. For this the method `setProject` already existed in the store. This is no real overhead because Vue is smart enough to only trigger listeners that use data of the modified state. By modifying only a copy of the view and submitting the modified result __once__ we can save us a lot of headache. PS: I'm not sure if there were any visible problems, because Vue is really fast and the reactivity system works quite well. Regardless of this we should try not to modify state unnecessarily. (cherry picked from commit 1e632397d29e9d45609b9271e00111c0a6cb2c57) --- frontend/src/stores/projects.ts | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/frontend/src/stores/projects.ts b/frontend/src/stores/projects.ts index 6af19be11..f132e6635 100644 --- a/frontend/src/stores/projects.ts +++ b/frontend/src/stores/projects.ts @@ -218,25 +218,30 @@ export const useProjectStore = defineStore('project', () => { } function setProjectView(view: IProjectView) { - const viewPos = projects.value[view.projectId].views.findIndex(v => v.id === view.id) + const views = [...projects.value[view.projectId].views] + const viewPos = views.findIndex(v => v.id === view.id) + if (viewPos !== -1) { - projects.value[view.projectId].views[viewPos] = view - projects.value[view.projectId].views.sort((a, b) => a.position < b.position ? -1 : 1) - setProject(projects.value[view.projectId]) - return + views[viewPos] = view + } else { + views.push(view) } + views.sort((a, b) => a.position < b.position ? -1 : 1) - projects.value[view.projectId].views.push(view) - projects.value[view.projectId].views.sort((a, b) => a.position < b.position ? -1 : 1) - - setProject(projects.value[view.projectId]) + setProject({ + ...projects.value[view.projectId], + views, + }) } function removeProjectView(projectId: IProject['id'], viewId: IProjectView['id']) { - const viewPos = projects.value[projectId].views.findIndex(v => v.id === viewId) - if (viewPos !== -1) { - projects.value[projectId].views.splice(viewPos, 1) - } + const project = projects.value[projectId] + const updatedViews = project.views.filter(v => v.id !== viewId) + + setProject({ + ...project, + views: updatedViews, + }) } return {