payload icon indicating copy to clipboard operation
payload copied to clipboard

afterChange Hook Only Executes for the Active Locale When Publishing Changes Across Multiple Locales

Open Collexi-Dev opened this issue 1 year ago • 1 comments

Describe the Bug

Description:

When publishing changes to a multi-locale document in Payload CMS, the afterChange hook is triggered only for the active locale (the locale open in the CMS interface where the “Publish Changes” button is clicked). This behavior occurs even though publishing updates all locales that have pending draft changes.

Expected Behavior:

The afterChange hook should execute for all locales that are updated during the publish action, ensuring that all relevant locales are processed (e.g., for revalidation or other post-change actions).

Current Behavior:

  1. The afterChange hook runs exclusively for the locale open in the CMS interface.
  2. Locales with updated content do not trigger the afterChange hook, potentially leaving them unprocessed (e.g., not revalidated or other necessary actions not performed).

Additional Context:

A workaround could involve looping through all locales in the afterChange hook, but this is inefficient and risks triggering unnecessary actions for locales that were not updated. A more optimal solution would be for the afterChange hook to automatically execute for all updated locales during the publish action.

Link to the code that reproduces this issue

https://github.com/Collexi-Dev/test-payload-3-stable

Reproduction Steps

The reproduction repo is just the current Payload template with added localization and logging in the afterChange hook.

  1. Create a multi-locale document (e.g., EN, NL).
  2. Make changes to both EN and NL locales and leave them as drafts.
  3. Open the NL locale in the CMS interface.
  4. Click “Publish Changes” in the NL locale.
  5. Observe that while the changes for both EN and NL are published, the afterChange hook is only triggered for the NL locale.

Which area(s) are affected? (Select all that apply)

area: core

Environment Info

Binaries:
  Node: 20.13.1
  npm: 10.5.2
  Yarn: 1.22.22
  pnpm: 9.12.2
Relevant Packages:
  payload: 3.0.0
  next: 15.0.0
  @payloadcms/db-mongodb: 3.0.0
  @payloadcms/email-nodemailer: 3.0.0
  @payloadcms/graphql: 3.0.0
  @payloadcms/live-preview: 3.0.0
  @payloadcms/live-preview-react: 3.0.0
  @payloadcms/next/utilities: 3.0.0
  @payloadcms/payload-cloud: 3.0.0
  @payloadcms/plugin-form-builder: 3.0.0
  @payloadcms/plugin-nested-docs: 3.0.0
  @payloadcms/plugin-redirects: 3.0.0
  @payloadcms/plugin-search: 3.0.0
  @payloadcms/plugin-seo: 3.0.0
  @payloadcms/richtext-lexical: 3.0.0
  @payloadcms/translations: 3.0.0
  @payloadcms/ui/shared: 3.0.0
  react: 19.0.0-rc-65a56d0e-20241020
  react-dom: 19.0.0-rc-65a56d0e-20241020
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 24.0.0: Mon Aug 12 20:52:41 PDT 2024; root:xnu-11215.1.10~2/RELEASE_ARM64_T6031
  Available memory (MB): 36864
  Available CPU cores: 14

Collexi-Dev avatar Nov 22 '24 14:11 Collexi-Dev

Ran into this same issue today.

rilrom avatar Nov 25 '24 06:11 rilrom

After talking this over with the team, we think that this is something users will need to implement on their own.

So in your afterChange hook, you would look for the _status property to switch from draft to published and then you would query each locale document and call the function you need to perform against each one.

Does that make sense? Let me know if I can help any further!

JarrodMFlesch avatar Jan 13 '25 16:01 JarrodMFlesch

After talking this over with the team, we think that this is something users will need to implement on their own.

So in your afterChange hook, you would look for the _status property to switch from draft to published and then you would query each locale document and call the function you need to perform against each one.

Does that make sense? Let me know if I can help any further!

@JarrodMFlesch Do you mean simply looping over all locales and triggering the code inside afterChange for each, unrelated to if the doc was actually updated or not? That's the workaround described in Additional Context and exactly the thing I wanted to avoid here, to unnecessarily trigger code for locales that aren't updated.

I'm not entirely sure why this wouldn't be seen as an actual bug though, you define hooks to execute code during specific events in the lifecycle. When you make changes across all locales and then publish all of them, all of the docs trigger an update and change from draft to published hence this should trigger the afterChange?

If this is not expected behaviour and we should loop over all locales every time the afterChange hook finds a draft that's published then I believe the docs should be updated to reflect that i.e. afterChange is only executed for the open document/locale when publishing.

Not sure if I'm missing something.

Collexi-Dev avatar Jan 13 '25 18:01 Collexi-Dev

@JarrodMFlesch could you please elaborate on the reasoning behind the teams decision?

rilrom avatar Jan 15 '25 04:01 rilrom

This issue has been automatically locked. Please open a new issue if this issue persists with any additional detail.

github-actions[bot] avatar Jan 17 '25 04:01 github-actions[bot]

Hi @Collexi-Dev @rilrom, I understand and agree that the behavior here is very confusing.

To the best of my understanding, this issue is due to the flow of our publishing process. This is currently what is happening:

  1. Publish all is selected
  2. The current document is updated and runs all hooks
  3. For others locales, document data gets overwritten with _status: published -> here we directly overwrite the data because we do not want all the hooks to run -> at this point in the process, we do not know what the receiving locale data looks like (i.e. what if the other locale was already published and therefore no data changed?) and then it is not possible to determine whether the afterChange should be run

Our dev team reinvestigated this issue and unfortunately there is no ideal or proposed solution yet. There were a couple approaches discussed but unfortunately it would either incur a large performance penalty or cause breaking changes in regards to how data is handled.

Until we land on a resolution, here are some things you could try:

  • As @JarrodMFlesch mentioned, you could expand your afterChange to fetch your other locale documents, compare the data and run your logic accordingly.
  • Similarly to how our publishSpecificLocale button works, you could add a custom Publish button which loops all locales and publishes them consecutively.

If you have any thoughts or suggestions, we would be happy to hear them. I apologize for the situation and appreciate the detailed issue here!

jessrynkar avatar Jan 21 '25 17:01 jessrynkar

Closing as not planned for now - planned to revisit fix in the future.

jessrynkar avatar Jan 28 '25 13:01 jessrynkar