AfterUpdate Lifecycle infinite loop

Hi,

Is it possible to restrict lifecycle method to user action and not API ?
Example when a user update an entry via Strapi dashboard I want to run the afterUpdate lifecycle that will update another entry. However via API if I do that it goes into an infinite loop obviously because → user update entry → afterUpdate triggers → update another entry → lifecycle trigger again → infinite loop…

Thank you,

Not currently because those lifecycles happen when a strapi.query().action() happens, which can be triggered from anywhere.

Can you propose any solution to this?

How can we change a value of an item when a user updates the content…?

Edit: Just realised you can change the data in the beforeUpdate hook OP,

Do this there and edit the reference to the object you want to update and no infinite loop.

1 Like

when i update in beforeUpdate hook, i get 2-3 loop, and in afterUpdate its infinite loop so “beforeUpdate” its better for me.

did you have same situation for “beforeUpdate” hook or your code executes only once?

      const { id } = result;
      if (id && !params?.data?.fromAfterUpdate) {
        const profile = await strapi.service("api::profile.profile").findOne(id, {
          populate: {
            course_category: "*",
            course_quizs: {
              populate: {
                questions: {
                  populate: "*",
                },
              },
            },
          },
        });
        // some action
        const isValidToApprove = isValidProfileToApprove(profile);

        await strapi.service("api::profile.profile").update(id, {
          data: {
            isValidToApprove: isValidToApprove,
            fromAfterUpdate: true, // some dummy param to validate.
          },
        });
      }

I had the exact same issue as OP, my afterUpdate code would enter into an infinite loop since it updated data into the same item. I solved it by using direct knex.js commands which apparently don’t trigger lifecycle hooks, this should be made clearer in the documentation…
Posting it here in case someone finds this thread with google like I did.
Here’s how:

async afterUpdate(event){
		const data = event.params.data
		const titre = data.Titre
		const date = data.date
		const id = event.params.where.id
		const relation = await strapi.db.query('api::radio-show.radio-show').findOne({
			where:{id: id},
			populate:{resident: true}
		})
		const resident = relation.resident.Name
		const toBeSlug = slugify(resident + " "+ titre + " " + dayjs(date).format("DD-MM-YYYY"))
		/* If the query engine was used to update the data, we would enter an infinite loop*/
		/* The following code doesnt enter the infinite loop because it interacts directly with the database with knex.js */
		const update = await strapi.db.connection("radio_shows").where({id: id}).update({slug:toBeSlug})
	}	

As you can see, it’s a custom slug creating system that uses a relation field as one of its variable.

1 Like

try this if you use strapi >= v4
In “src/api/post/content-types/post/lifecycle.js” (let create lifecycle.js if file does not exist).

module.exports = {
  async afterFindOne(event) {
    const { result } = event;
    await strapi.db
      .connection("posts")
      .where({ id: result.id })
      .update({ views: parseInt(result?.views || 0) + 1 });
  },
};