fix: update select options when the options prop changes (#6878)
Fixes https://github.com/payloadcms/payload/issues/6869 Before, options from props were being stored in state and would not update when props changed. Now options are memoized and will update when the incoming `options` prop changes.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
'use client'
|
||||
|
||||
import type { Option } from 'payload'
|
||||
|
||||
import { SelectField, useField } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export const CustomSelect = ({ path }: { path: string }) => {
|
||||
const { setValue, value } = useField<string>({ path })
|
||||
const [options, setOptions] = React.useState<{ label: string; value: string }[]>([])
|
||||
|
||||
React.useEffect(() => {
|
||||
const fetchOptions = () => {
|
||||
const fetchedOptions = [
|
||||
{
|
||||
label: 'Label 1',
|
||||
value: 'value1',
|
||||
},
|
||||
{
|
||||
label: 'Label 2',
|
||||
value: 'value2',
|
||||
},
|
||||
]
|
||||
setOptions(fetchedOptions)
|
||||
}
|
||||
void fetchOptions()
|
||||
}, [])
|
||||
|
||||
const onChange = (selected: Option | Option[]) => {
|
||||
const options = Array.isArray(selected) ? selected : [selected]
|
||||
setValue(options.map((option) => (typeof option === 'string' ? option : option.value)))
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<SelectField
|
||||
hasMany
|
||||
name={path}
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
path={path}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
19
test/admin/collections/CustomFields/index.ts
Normal file
19
test/admin/collections/CustomFields/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
import { customFieldsSlug } from '../../slugs.js'
|
||||
import { CustomSelect } from './components/CustomSelect.js'
|
||||
|
||||
export const CustomFields: CollectionConfig = {
|
||||
slug: customFieldsSlug,
|
||||
fields: [
|
||||
{
|
||||
name: 'customSelectField',
|
||||
type: 'text',
|
||||
admin: {
|
||||
components: {
|
||||
Field: CustomSelect,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import path from 'path'
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
||||
import { CustomFields } from './collections/CustomFields/index.js'
|
||||
import { CustomIdRow } from './collections/CustomIdRow.js'
|
||||
import { CustomIdTab } from './collections/CustomIdTab.js'
|
||||
import { CustomViews1 } from './collections/CustomViews1.js'
|
||||
@@ -116,6 +117,7 @@ export default buildConfigWithDefaults({
|
||||
CollectionNoApiView,
|
||||
CustomViews1,
|
||||
CustomViews2,
|
||||
CustomFields,
|
||||
CollectionGroup1A,
|
||||
CollectionGroup1B,
|
||||
CollectionGroup2A,
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
slugPluralLabel,
|
||||
} from '../../shared.js'
|
||||
import {
|
||||
customFieldsSlug,
|
||||
customIdCollectionId,
|
||||
customViews2CollectionSlug,
|
||||
disableDuplicateSlug,
|
||||
@@ -70,6 +71,7 @@ describe('admin1', () => {
|
||||
let postsUrl: AdminUrlUtil
|
||||
let globalURL: AdminUrlUtil
|
||||
let customViewsURL: AdminUrlUtil
|
||||
let customFieldsURL: AdminUrlUtil
|
||||
let disableDuplicateURL: AdminUrlUtil
|
||||
let serverURL: string
|
||||
let adminRoutes: ReturnType<typeof getAdminRoutes>
|
||||
@@ -89,6 +91,7 @@ describe('admin1', () => {
|
||||
postsUrl = new AdminUrlUtil(serverURL, postsCollectionSlug)
|
||||
globalURL = new AdminUrlUtil(serverURL, globalSlug)
|
||||
customViewsURL = new AdminUrlUtil(serverURL, customViews2CollectionSlug)
|
||||
customFieldsURL = new AdminUrlUtil(serverURL, customFieldsSlug)
|
||||
disableDuplicateURL = new AdminUrlUtil(serverURL, disableDuplicateSlug)
|
||||
|
||||
const context = await browser.newContext()
|
||||
@@ -481,6 +484,16 @@ describe('admin1', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('custom fields', () => {
|
||||
describe('select field', () => {
|
||||
test('should render custom select options', async () => {
|
||||
await page.goto(customFieldsURL.create)
|
||||
await page.locator('#field-customSelectField .rs__control').click()
|
||||
await expect(page.locator('#field-customSelectField .rs__option')).toHaveCount(2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('API view', () => {
|
||||
test('collection — should not show API tab when disabled in config', async () => {
|
||||
await page.goto(postsUrl.collection(noApiViewCollectionSlug))
|
||||
|
||||
@@ -11,6 +11,7 @@ export const hiddenCollectionSlug = 'hidden-collection'
|
||||
export const noApiViewCollectionSlug = 'collection-no-api-view'
|
||||
export const disableDuplicateSlug = 'disable-duplicate'
|
||||
export const uploadCollectionSlug = 'uploads'
|
||||
export const customFieldsSlug = 'custom-fields'
|
||||
export const collectionSlugs = [
|
||||
usersCollectionSlug,
|
||||
customViews1CollectionSlug,
|
||||
@@ -23,6 +24,7 @@ export const collectionSlugs = [
|
||||
group2Collection2Slug,
|
||||
hiddenCollectionSlug,
|
||||
noApiViewCollectionSlug,
|
||||
customFieldsSlug,
|
||||
disableDuplicateSlug,
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user