Skip to content

Commit 5cd0c7e

Browse files
fix: layout preferences for array/blocks were being saved twice in dev mode (#7396)
Fixes an issue where preferences for array/block collapsible's were not being set correctly. React strict mode surfaced this issue.
1 parent cd592cb commit 5cd0c7e

File tree

5 files changed

+90
-62
lines changed

5 files changed

+90
-62
lines changed

packages/ui/src/fields/Array/index.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { DraggableSortable } from '../../elements/DraggableSortable/index.js'
1111
import { ErrorPill } from '../../elements/ErrorPill/index.js'
1212
import { useFieldProps } from '../../forms/FieldPropsProvider/index.js'
1313
import { useForm, useFormSubmitted } from '../../forms/Form/context.js'
14+
import { extractRowsAndCollapsedIDs, toggleAllRows } from '../../forms/Form/rowHelpers.js'
1415
import { NullifyLocaleField } from '../../forms/NullifyField/index.js'
1516
import { useField } from '../../forms/useField/index.js'
1617
import { withCondition } from '../../forms/withCondition/index.js'
@@ -28,7 +29,7 @@ import './index.scss'
2829

2930
const baseClass = 'array-field'
3031

31-
export const _ArrayField: React.FC<ArrayFieldProps> = (props) => {
32+
export const ArrayFieldComponent: React.FC<ArrayFieldProps> = (props) => {
3233
const {
3334
name,
3435
CustomDescription,
@@ -159,16 +160,27 @@ export const _ArrayField: React.FC<ArrayFieldProps> = (props) => {
159160

160161
const toggleCollapseAll = useCallback(
161162
(collapsed: boolean) => {
162-
dispatchFields({ type: 'SET_ALL_ROWS_COLLAPSED', collapsed, path, setDocFieldPreferences })
163+
const { collapsedIDs, updatedRows } = toggleAllRows({
164+
collapsed,
165+
rows,
166+
})
167+
dispatchFields({ type: 'SET_ALL_ROWS_COLLAPSED', path, updatedRows })
168+
setDocFieldPreferences(path, { collapsed: collapsedIDs })
163169
},
164-
[dispatchFields, path, setDocFieldPreferences],
170+
[dispatchFields, path, rows, setDocFieldPreferences],
165171
)
166172

167173
const setCollapse = useCallback(
168174
(rowID: string, collapsed: boolean) => {
169-
dispatchFields({ type: 'SET_ROW_COLLAPSED', collapsed, path, rowID, setDocFieldPreferences })
175+
const { collapsedIDs, updatedRows } = extractRowsAndCollapsedIDs({
176+
collapsed,
177+
rowID,
178+
rows,
179+
})
180+
dispatchFields({ type: 'SET_ROW_COLLAPSED', path, updatedRows })
181+
setDocFieldPreferences(path, { collapsed: collapsedIDs })
170182
},
171-
[dispatchFields, path, setDocFieldPreferences],
183+
[dispatchFields, path, rows, setDocFieldPreferences],
172184
)
173185

174186
const hasMaxRows = maxRows && rows.length >= maxRows
@@ -314,4 +326,4 @@ export const _ArrayField: React.FC<ArrayFieldProps> = (props) => {
314326
)
315327
}
316328

317-
export const ArrayField = withCondition(_ArrayField)
329+
export const ArrayField = withCondition(ArrayFieldComponent)

packages/ui/src/fields/Blocks/index.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { useDrawerSlug } from '../../elements/Drawer/useDrawerSlug.js'
1313
import { ErrorPill } from '../../elements/ErrorPill/index.js'
1414
import { useFieldProps } from '../../forms/FieldPropsProvider/index.js'
1515
import { useForm, useFormSubmitted } from '../../forms/Form/context.js'
16+
import { extractRowsAndCollapsedIDs, toggleAllRows } from '../../forms/Form/rowHelpers.js'
1617
import { NullifyLocaleField } from '../../forms/NullifyField/index.js'
1718
import { useField } from '../../forms/useField/index.js'
1819
import { withCondition } from '../../forms/withCondition/index.js'
@@ -168,16 +169,27 @@ const BlocksFieldComponent: React.FC<BlocksFieldProps> = (props) => {
168169

169170
const toggleCollapseAll = useCallback(
170171
(collapsed: boolean) => {
171-
dispatchFields({ type: 'SET_ALL_ROWS_COLLAPSED', collapsed, path, setDocFieldPreferences })
172+
const { collapsedIDs, updatedRows } = toggleAllRows({
173+
collapsed,
174+
rows,
175+
})
176+
dispatchFields({ type: 'SET_ALL_ROWS_COLLAPSED', path, updatedRows })
177+
setDocFieldPreferences(path, { collapsed: collapsedIDs })
172178
},
173-
[dispatchFields, path, setDocFieldPreferences],
179+
[dispatchFields, path, rows, setDocFieldPreferences],
174180
)
175181

176182
const setCollapse = useCallback(
177183
(rowID: string, collapsed: boolean) => {
178-
dispatchFields({ type: 'SET_ROW_COLLAPSED', collapsed, path, rowID, setDocFieldPreferences })
184+
const { collapsedIDs, updatedRows } = extractRowsAndCollapsedIDs({
185+
collapsed,
186+
rowID,
187+
rows,
188+
})
189+
dispatchFields({ type: 'SET_ROW_COLLAPSED', path, updatedRows })
190+
setDocFieldPreferences(path, { collapsed: collapsedIDs })
179191
},
180-
[dispatchFields, path, setDocFieldPreferences],
192+
[dispatchFields, path],
181193
)
182194

183195
const hasMaxRows = maxRows && rows.length >= maxRows

packages/ui/src/forms/Form/fieldReducer.ts

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -309,68 +309,27 @@ export function fieldReducer(state: FormState, action: FieldAction): FormState {
309309
}
310310

311311
case 'SET_ROW_COLLAPSED': {
312-
const { collapsed, path, rowID, setDocFieldPreferences } = action
313-
314-
const arrayState = state[path]
315-
316-
const { collapsedRowIDs, matchedIndex } = state[path].rows.reduce(
317-
(acc, row, index) => {
318-
const isMatchingRow = row.id === rowID
319-
if (isMatchingRow) acc.matchedIndex = index
320-
321-
if (!isMatchingRow && row.collapsed) acc.collapsedRowIDs.push(row.id)
322-
else if (isMatchingRow && collapsed) acc.collapsedRowIDs.push(row.id)
323-
324-
return acc
325-
},
326-
{
327-
collapsedRowIDs: [],
328-
matchedIndex: undefined,
329-
},
330-
)
331-
332-
if (matchedIndex > -1) {
333-
arrayState.rows[matchedIndex].collapsed = collapsed
334-
setDocFieldPreferences(path, { collapsed: collapsedRowIDs })
335-
}
312+
const { path, updatedRows } = action
336313

337314
const newState = {
338315
...state,
339316
[path]: {
340-
...arrayState,
317+
...state[path],
318+
rows: updatedRows,
341319
},
342320
}
343321

344322
return newState
345323
}
346324

347325
case 'SET_ALL_ROWS_COLLAPSED': {
348-
const { collapsed, path, setDocFieldPreferences } = action
349-
350-
const { collapsedRowIDs, rows } = state[path].rows.reduce(
351-
(acc, row) => {
352-
if (collapsed) acc.collapsedRowIDs.push(row.id)
353-
354-
acc.rows.push({
355-
...row,
356-
collapsed,
357-
})
358-
359-
return acc
360-
},
361-
{
362-
collapsedRowIDs: [],
363-
rows: [],
364-
},
365-
)
366-
367-
setDocFieldPreferences(path, { collapsed: collapsedRowIDs })
326+
const { path, updatedRows } = action
368327

369328
return {
370329
...state,
371330
[path]: {
372331
...state[path],
373-
rows,
332+
rows: updatedRows,
374333
},
375334
}
376335
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { Row } from 'payload'
2+
3+
export const extractRowsAndCollapsedIDs = ({
4+
collapsed,
5+
rowID,
6+
rows,
7+
}: {
8+
collapsed: boolean
9+
rowID: string
10+
rows: Row[]
11+
}): {
12+
collapsedIDs: string[]
13+
updatedRows: Row[]
14+
} => {
15+
return rows.reduce(
16+
(acc, row) => {
17+
if (rowID === row.id) row.collapsed = collapsed
18+
if (row.collapsed) acc.collapsedIDs.push(row.id)
19+
acc.updatedRows.push(row)
20+
return acc
21+
},
22+
{
23+
collapsedIDs: [],
24+
updatedRows: [],
25+
},
26+
)
27+
}
28+
29+
export const toggleAllRows = ({
30+
collapsed,
31+
rows,
32+
}): {
33+
collapsedIDs: string[]
34+
updatedRows: Row[]
35+
} => {
36+
return rows.reduce(
37+
(acc, row) => {
38+
row.collapsed = collapsed
39+
if (collapsed) acc.collapsedIDs.push(row.id)
40+
acc.updatedRows.push(row)
41+
return acc
42+
},
43+
{
44+
collapsedIDs: [],
45+
updatedRows: [],
46+
},
47+
)
48+
}

packages/ui/src/forms/Form/types.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Data, Field, FormField, FormState, User } from 'payload'
1+
import type { Data, Field, FormField, FormState, Row, User } from 'payload'
22
import type React from 'react'
33
import type { Dispatch } from 'react'
44

@@ -141,18 +141,15 @@ export type ADD_SERVER_ERRORS = {
141141
}
142142

143143
export type SET_ROW_COLLAPSED = {
144-
collapsed: boolean
145144
path: string
146-
rowID: string
147-
setDocFieldPreferences: (field: string, fieldPreferences: { [key: string]: unknown }) => void
148145
type: 'SET_ROW_COLLAPSED'
146+
updatedRows: Row[]
149147
}
150148

151149
export type SET_ALL_ROWS_COLLAPSED = {
152-
collapsed: boolean
153150
path: string
154-
setDocFieldPreferences: (field: string, fieldPreferences: { [key: string]: unknown }) => void
155151
type: 'SET_ALL_ROWS_COLLAPSED'
152+
updatedRows: Row[]
156153
}
157154

158155
export type FieldAction =

0 commit comments

Comments
 (0)