How to trigger a page refresh in the Admin UI after a Lifecycle Hook?

System Information
  • Strapi Version: 4.3.4
  • Operating System: macOS
  • Database: PostgreSQL
  • Node Version: 14.20.0
  • NPM Version: 6.14.17
  • Yarn Version: 1.22.19

I’ve implemented an afterUpdate hook on Collection Type A that creates new items in Collection Type B, during the execution of the function, it creates relationships between the item in Collection Type A and the new items in Collection Type B.

However, the UI will not show updates to the data (including the new relationships) without the user refreshing the page (not very intuitive). How do I tell the Admin UI from the lifecycle hook that a refresh is required?

I’ve seen the UI show a message when the server needs to restart, so I’m hoping this has been solved already.

3 Likes

Have you find the solution to this problem ?
@DMehaffy @Eventyret Can you please help here ?

1 Like

I haven’t found a solution to this problem as of yet

There isn’t really a way for the afterX lifecycles as this part is done after the response is already being sent to the user

Thanks for your reply @DMehaffy,

Is there by any chance a hook or another strategy in the admin/frontend for actions after a response is received?

@dallasclark

Like @DMehaffy said afterX runs after the response has been sent.
Depending on your “willingness” you can workaround that issue by simply spin up a loading circle after the user saves your entity and wait for a second until you perform the refresh yourself.

The better but not as simple solution would be to let your afterCreate fill an attribute that onSave is always getting nulled.
That way you can follow up a short waiting time until you fetch the entry again, check for your afterCreateDone-Attribute and if this is set you can safely perform a refresh.

When I use the afterUpdate lifecycle, the query to the API does not return a response until this lifecycle hook is completed. My afterUpdate lifecycle hook takes roughly 50-60 seconds to complete so the UI freezes whilst the “Save” or “Publish” buttons are showing the loading animation.

When an afterUpdate lifecycle hook fails, the response fails. So I’m not confident the answers above about the response is already sent to the user before the lifecycle hook is triggered are accurate.

It would be great if I can either:

  • Send back a response that will trigger an update to the UI (if this frontend logic is already implemented), OR
  • Create frontend logic to refresh/update the data in the UI after every publish or save request

The problem is Strapi uses CSR (React) and we can’t have the frontend constantly pinging. I would suggest implementing a try/catch in your afterX to handle any errors so the response is returned on time.

@DMehaffy there are no errors …

The afterUpdate lifecycle makes connections to external services that are processing the data. The front end is showing loading animations for the full duration whilst this lifecycle is processing the request.

Did anyone here ever get this to work? If so, could you provide a code example?

Unfortunately not … yet

Anyone have leads on how to trigger a refresh in Strapi Admin UI at all? Having the same issue as @dallasclark.

@jack_tmrrw In the latest version of Strapi (v4.5), we’ve seen improvements in the admin panel when data is modified by the server. When new relationships between one entry are created with other entries on the server, we’ve seen the new relationships load automatically.

However, it’s still not resolved across the rest of the data on the Admin Panel’s form.

1 Like

I maby found a solution.
You could register a injectContentManagerComponent in a plugin and register a react component to inject into a injection zone inside of the ContentManager edit window. inside of the injection zone you could call window.location.reload() what will trigger a reload of the whole page you should be able to see initialData from useCMEditViewDataManager change as soon as you save it should change.
You should be able to use that to check for when a save happens and call a reload.

3 Likes

Worked for me, thanks a lot! Added some custom logic to lifecycle hooks and needed to refresh the page (list view as well) after that, this was exactly what I was looking for.

Can you please provide a code snippet?

Is this injected in after an afterUpdate hook has completed?

Some of my afterUpdate hooks take 1 second, some take 10 seconds.

I am interested to know the answer as well, @dallasclark can you give this component a try?

import { useCMEditViewDataManager } from '@strapi/helper-plugin';
import React, { useEffect, useRef, useState } from 'react'
import { isEqual } from 'lodash/fp'

export const AfterUpdateReload = () => {
    const data = useCMEditViewDataManager()
    const { initialData, slug } = data;
    const [lastInitialData] = useState(initialData)
    const supportedSlug = ["api::product.product"]

    useEffect(() => {
        if(!supportedSlug.includes(slug ?? "")) return 
        if(isEqual(initialData, lastInitialData)) return

        window.location.reload()
    }, [initialData])

    return (
        <></>
    )
}
// ./src/admin/app.ts
import { AfterUpdateReload } from './extensions/AfterUpdateReload'

export default {
  config: {
    locales: [

    ],
    tutorials: false,
    notifications: { releases: false },
  },
  bootstrap(app) {
    app.injectContentManagerComponent("editView", "informations", {
      name: "my-compo",
      Component: AfterUpdateReload,
    });
  },
};

it works but definitely not ideal. It makes sense for Strapi not wait for result of afterUpdate by default, but it should be configurable. So webhook will cover async communication, and lifecycle hooks will cover sync communication with other systems

1 Like

Thanks alot, that solved my problem and I can trigger a reload when certain parameters have changed!

Although the build fails when importing the file in the app.js. So I had to put the AfterUpdateReload component directly into the app.js. Not beautiful, but it works.

A little hacky, but it works for me:

import { useQueryClient } from "react-query";
...  
const queryClient = useQueryClient();
queryClient.invalidateQueries(["relation"]);

This code refreshing relations without reload page overall.

1 Like