Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

'RangeError: Maximum call stack size exceeded' when using beforeChange on a field

default discord avatar
waterlord9311 months ago
5

First time working with beforeChange so its probably something stupid...


What am i doing wrong?



i want to set value for "updatedAt" in the fieldsData group when create or update operation is triggered, but only if it changes "ownedFields" inside the fieldsData group


In collection i have some other fields but they are not important, no hooks etc and saving collection works if i comment out beforeChange hook in 'ownedFields'..



{


name: 'fieldsData',


type: 'group',


fields: [


{


name: 'updatedAt',


type: 'text',


hidden: true,


},


{


name: 'ownedFields',


type: 'array',


required: false,


fields: [


{


name: 'fieldIndex',


type: 'number',


required: true,


},


],


hooks: {


beforeChange: [


// set updatedAt


({ data, field }) => {


const typedData = data as Partial<IPlayerInventory>;



if (field.name == 'ownedFields' && typedData.fieldsData) {


typedData.fieldsData.updatedAt = new Date().toISOString();


console.log('beforeChange.ownedFields', typedData);


return typedData;


}



return data;


},


],


},


},


],


}

  • default discord avatar
    notchr11 months ago
    @351380945443487745

    Hmmm



    I would probably do a beforeOperation on the collection level



    Let me know when you're back

  • default discord avatar
    waterlord9311 months ago

    i am back now

  • default discord avatar
    waterlord9311 months ago

    looking at it now with fresh eyes, is this maybe a job for afterChange? can I write to a field in afterChange?



    ah i get it why it gets into infinite loop... it expects value as return type, not whole object and i have been returning data



    so i think you are right, i should probably do this on collection level beforeOperation, rather than field level



    if someone ends up here via search with same issue, here is how i solved it:



    const populateFieldsUpdatedAt: CollectionBeforeOperationHook = async ({


    args, // original arguments passed into the operation


    operation, // name of the operation


    req, // full express request


    }) => {


    if (!req.user) {


    throw 'Not Authenticated';


    }



    if (!(operation == 'update' || operation == 'create')) {


    return args;


    }



    const typedData = args.data as Partial<IPlayerInventory>;



    if (typedData.fieldsData && typedData.fieldsData.ownedFields) {


    typedData.fieldsData.updatedAt = new Date().toISOString();



    return {


    ...args,


    data: typedData,


    };


    }



    return args; // return modified operation arguments as necessary


    };



    export const PlayerInventories: CollectionConfig = {


    slug: 'player-inventory',


    typescript: {


    interface: 'IPlayerInventory',


    },


    admin: {


    useAsTitle: 'id',


    },


    hooks: {


    beforeOperation: [populateFieldsUpdatedAt],


    },


    fields: [


    {


    name: 'fieldsData',


    type: 'group',


    fields: [


    {


    name: 'updatedAt',


    type: 'date',


    hidden: true,


    },


    {


    name: 'ownedFields',


    type: 'array',


    required: false,


    fields: [


    {


    name: 'fieldIndex',


    type: 'number',


    required: true,


    },


    ],


    },


    ],


    },


    ],


    };



    @1049775120559898725

    thanks again for your help mate

  • default discord avatar
    notchr11 months ago

    No prob, glad you solved it!

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.