The best way to build a modern backend + admin UI. No black magic, all TypeScript, and fully open-source, Payload is both an app framework and a headless CMS.
MIT License
Bot releases are hidden (Show)
Published by denolfe about 2 months ago
Published by denolfe about 2 months ago
Published by denolfe about 2 months ago
Published by denolfe about 2 months ago
Published by denolfe about 2 months ago
Published by denolfe about 2 months ago
handles custom collection description components (#7789) (cb9b80a)
If you were previously defining a custom description component on a collection, simply move it into the correct position.
Old:
{
admin: {
components: {
edit: {
Description: ''
}
}
}
}
New:
{
admin: {
components: {
Description: ''
}
}
}
Published by denolfe 2 months ago
Published by denolfe 2 months ago
Published by denolfe 2 months ago
Published by denolfe 2 months ago
Published by denolfe 2 months ago
Published by denolfe 2 months ago
Published by denolfe 2 months ago
Published by denolfe 2 months ago
false
as PayloadComponent which signals that the component should not be rendered (#7682) (49a2d70)Published by denolfe 2 months ago
leave-without-saving
modal after navigating from Leave anyway
button (#7661) (806c22e)Published by denolfe 2 months ago
Follow along with the migration guide below for full details on each of the changes. Please reference this document as you migrate your own apps to this release.
So what's included in this release? By far the biggest change comes from this PR (migration guide below).
This PR made significant optimizations to the underlying codebase
For a complete list of all other bug fixes and features included in this release, scroll to the bottom of this document.
To migrate from beta.78
to beta.79
, you'll need to make a few changes to your Payload Config. Although this release is substantial, migration is relatively straightforward, with most of the changes only effecting the use of Custom Components.
The following changes are required of all projects:
Add a blank "import map" to your project. Create a new file called importMap.js
and add it to /app/(payload)/admin/importMap.js
in your app with the following content:
export const importMap = {}
Payload will dynamically inject this file with imports at compile time. If you are using a custom admin route, change the path accordingly.
It is recommended to run the payload generate:importMap
command after you're done with the migration (make sure you follow all migration steps below first). Additionally, if the automatic import map generation fails, try running payload generate:importMap
.
Thread the "import map" file through your Root Layout, Root Page, and Not Found Pages:
The Root Layout at /app/(payload)/layout.tsx
:
// ...
import { importMap } from "./admin/importMap.js"
//...
const Layout = ({ children }: Args) => (
<RootLayout config={configPromise} importMap={importMap}>
{children}
</RootLayout>
)
export default Layout
The Root Page at /app/(payload)/admin/[[...segments]]/page.tsx
:
// ...
import { importMap } from "../importMap.js"
//...
const Page = ({ params, searchParams }: Args) =>
RootPage({ config, importMap, params, searchParams })
export default Page
The Not Found Page at /app/(payload)/admin/[[...segments]]/not-found.tsx
:
// ...
import { importMap } from "../importMap.js"
//...
const NotFound = ({ params, searchParams }: Args) =>
NotFoundPage({ config, importMap, params, searchParams })
export default NotFound
If you are importing the Payload Config in a Node.js environment, there is no longer a need for a special loader to process it. Instead, you can simply import the Payload Config directly. To migrate, remove the importConfig
and importWithoutClientFiles
functions from your Node.js code:
Old:
import { importConfig, importWithoutClientFiles } from "payload"
import { join } from "path"
const config = importConfig(join(__dirname, "payload.config.js"))
const configWithoutClientFiles = importWithoutClientFiles(
join(__dirname, "payload.config.js")
)
New:
import config from "./payload.config.js"
If you are not using Custom Components in your applications, then you are done! If you are using Custom Components, please continue reading.
If you are using Custom Components in your application, please follow these next steps. Not all of these changes will apply to every project. So first, review this list of changes, and if a change applies to yours, scroll down to that individual section for full details:
useConfig
hook usage (if applicable)useComponentMap
hook usage (if applicable)useFieldProps
hook usage (if applicable)Here's a full breakdown of each step:
If you are using Custom Components in your Payload Config, the pattern for defining them has changed. You'll need to update your Custom Component definitions to use "component paths" instead of direct imports. To migrate, pass the path to the component's file:
Old:
import { MyCustomComponent } from './MyCustomComponent.js'
// ...
{
// ...
admin: {
components: {
Label: MyCustomComponent
},
},
}
New:
{
// ...
admin: {
components: {
// NOTE: this path is relative to your `baseDir`, NOT the importing file
// The `#` character is used to specify the export name, if necessary
Label: '/collections/Posts/MyServerComponent.js#MyExportName',
},
},
}
Regarding the extension in the component path: you'd write it as if you were to write an import statement yourself. Few examples, assuming the imports are done from the base directory:
If you'd previously write import { sth } from './file.js'
the component path would be '/file.js#sth'
if you'd previously write import { sth } from './file'
the component path would be '/file#sth'
if you'd previously write import file from './file.tsx'
the component path would be '/file.tsx'
or '/file.tsx#default'
Alternatively, you can also define the custom component as a "PayloadComponent" in the Payload Config. This allows you to pass in client-side vs server-side props explicitly, which get automatically sanitized from the client. Previously, you'd have to use an HOC, or a utility such as withMergedProps
in order to do that.
{
// ...
admin: {
components: {
Label: {
path: '/collections/Posts/MyServerComponent.js#MyExportName',
// exportName: 'MyComponent2' // optional if you wish to omit the export name from the path
clientProps: {
someClientProp: 'someValue'
},
serverProps: {
someServerProp: () => 'someValue'
}
}
},
},
}
More info regarding how the new component path imports work can be found in our custom component imports docs
useConfig
hook changesIf you are using the useConfig
React hook anywhere in your Custom Components, its return value has changed in shape. The config
is now a property within the context object, rather than the return value itself. To migrate, simply destructure the config
property from the return value of useConfig
:
Old:
import { useConfig } from "@payloadcms/ui"
// ...
const config = useConfig()
New:
import { useConfig } from "@payloadcms/ui"
// ...
const { config } = useConfig()
useComponentMap
hook was deprecatedIf you were using the useComponentMap
React hook anywhere in your Custom Components, it no longer exists. Instead, it has been merged into useConfig
. To migrate, swap it out for the new hook:
Old:
import { useComponentMap } from "@payloadcms/ui"
// ...
const { componentMap, getComponentMap } = useComponentMap()
const collectionComponentMap = getComponentMap({ collectionSlug: "pages" })
New:
import { useConfig } from "@payloadcms/ui"
// ...
const { config, getEntityConfig } = useConfig()
const collectionClientConfig = getEntityConfig({ collectionSlug: "pages" })
If you were using Custom Fields anywhere in your code, their props have changed in shape. Previously, field props were spread in at the top-level of the component. Now, they are nested under the field
key, which is a client-safe version of that field's config. To migrate, simply change your prop references to be nested under field
:
Old:
import type { TextFieldProps } from "payload"
const MyCustomField: : React.FC<TextFieldProps> = ({ name }) => {
return <div>{name}</div>
}
New:
import type { TextFieldProps } from "payload"
const MyCustomField: : React.FC<TextFieldProps> = ({ field: { name } }) => {
return <div>{name}</div>
}
This example demonstrates a simple text field, but this same thing applies to all field types. The type naming convention is consistent across all field types, so you can easily find the type definitions for your respective field type.
useFieldProps
is not necessary anymoreIf you were using the useFieldProps
hook in your Custom Client Components, this is no longer needed. Now, client components are automatically detected and rendered client-side which direct props. To migrate your Custom Client Components, simply remove the useFieldProps
hook from your component and read directly from props:
Old:
"use client"
import type { TextFieldProps } from "payload"
import { useFieldProps } from "@payloadcms/ui"
const MyCustomClientComponent: React.FC<TextFieldProps> = () => {
const { path } = useFieldProps()
return <div>{path}</div>
}
New:
"use client"
import type { TextFieldProps } from "payload"
const MyCustomClientComponent: React.FC<TextFieldProps> = ({
field: { _path },
}) => {
return <div>{_path}</div>
}
The shape of Custom Views and Custom Tabs has changed. Previously, you could define Custom Views and Tabs top-level in the config object OR as a configuration object. Now, you can only define them as a configuration object. For this reason, the keys have changed in casing to reflect the new shape (CapitalCase
denotes a React component, camelCase
denotes a regular object). To migrate, simply change the casing of of these keys within your Payload Config:
Old:
{
// ...
admin: {
components: {
views: {
Edit: {
Default: {
Tab: MyCustomTab
},
API: MyCustomAPIView
}
}
}
}
}
New:
{
// ...
admin: {
components: {
views: {
edit: {
default: {
tab: {
// ...
}
},
api: {
// ...
}
}
}
}
}
}
This example demonstrates only a subset of the Custom Views that are available in the Payload Config. The same change applies to all Custom Views and Tabs, such as admin.views.account
at the root-level, or admin.views.list
on Collection Configs.
This release also includes other miscellaneous features and fixes, including:
This lowers the module count by 31 modules
BREAKING: Migration-related lexical modules are now exported from
@payloadcms/richtext-lexical/migrate
instead of
@payloadcms/richtext-lexical
Published by denolfe 2 months ago
relationships
with drafts
enabled (#7570) (8d12037)ArrayCell
when length is 1 (#7586) (f88cef5)inflight
package (#6558) (eca1517), closes #6492
relationship
& upload
field population in versions
(#7533) (9865ae9)relationships
with not_equals
operator (#7573) (efa56ce), closes #5212 #6278
relationships
with drafts
enabled (#7565) (907d7d1), closes #6880
hasMany
text going outside of input boundaries (#7454) (1a0ef48), closes #6034
ArrayCell
when length is 1 (#7585) (fc4d24a), closes #6099