Search code examples
javascriptarraystypescriptbotframework

An array is modified when i call shift on another array


I know this is a weird incident and question , but i am having an issue where i have two arrays of objects "Reponses" and "Questions" . at one point in my program i remove the first element of an object in "Questions" by using shift() and the second array "Reponses" is modified in the same way and i am never calling shift() on it . here is the code :

private async Sousstep(stepContext: WaterfallStepContext): Promise<DialogTurnResult> {
    const siteDetails = stepContext.options as SiteDetails;
    
    //  IF OUI ----- IF NON ------ 
    if (Questions[0].sousquestions.length === 1 && Questions.length === 1) { siteDetails.skip = true; return await stepContext.next('next'); }
    if (!siteDetails.exit && !siteDetails.skip) {
         Reponses[0].sousquestions[0]
        const switchvar = Questions[0]
        const id = Questions[0].sousquestions[0].id
       
        if (Questions[0].sousquestions.length > 1) { siteDetails.skip = true; Questions[0].sousquestions.shift() } else {

            siteDetails.sousquestion = false;

            if (Questions.length > 1) { Questions.shift(); siteDetails.skip = true; return await stepContext.replaceDialog(WATERFALL_DIALOG, siteDetails) }
        }
        
        if (stepContext.result.value === 'Oui') {                     // CONTINUE ICI SI OUI ALORS ON EFFECTUE ON PROMPTE L4UTILISATEUR POUR SOIT NUMBER OU BOOLEAN OU STRING
            siteDetails.skip = false;

            switch (switchvar.sousquestions[0].type) {
                case 'number':
                    return await stepContext.prompt(NUMBER_PROMPT, { prompt: `Saisissez le degré D'intensité de 0 à 9 , Pendant le mois avant avoir eu le Covid" ?` });
                    break;
                case 'boolean':
                  
                    let elementPos = Reponses.map(function (x) { return x.id; }).indexOf(Questions[0].id);
                   
                    let souselementPos = Reponses[elementPos].sousquestions.map(function (x) { return x.id; }).indexOf(id);
                    console.log(Reponses[elementPos].sousquestions)
                   
                    Reponses[elementPos].sousquestions[souselementPos].reponse = true;
                   
                    siteDetails.skip = true 
                    return await stepContext.replaceDialog(WATERFALL_DIALOG, siteDetails);
                    break;
                case 'string':

                    return await stepContext.prompt(TEXT_PROMPT, { prompt: ` Donnez le nom ou pseudo de votre Signe Général ` });

                    break;
                
                default:
                    
                    break;
            }
        }
        else { if (typeof stepContext.result === 'number') {
                    let elementPos = Reponses.map(function (x) { return x.id; }).indexOf(Questions[0].id);
                    let souselementPos = Reponses[elementPos].sousquestions.map(function (x) { return x.id; }).indexOf(Questions[0].sousquestions[0].id);
                    Reponses[elementPos].sousquestions[souselementPos].value = stepContext.result;
                    console.log(Reponses[elementPos].sousquestions)

                    return await stepContext.replaceDialog(WATERFALL_DIALOG, siteDetails);
        } else {
            
         siteDetails.skip = true; return await stepContext.replaceDialog(WATERFALL_DIALOG, siteDetails);} }


    } else {

        return await stepContext.next(null);
    }
}

Solution

  • DB.query().then((res) => { Questions = res; Reponses = res ; 
    console.log(Reponses[0].sousquestions)})
    
    

    With the above code, both Questions and Responses will point to the same address in memory. Changing one will change the another.

    
    DB.query().then((res) => { Questions = JSON.parse(JSON.stringify(res)); 
    Reponses = JSON.parse(JSON.stringify(res)) ; console.log(Reponses[0].sousquestions)})
    
    

    This JSON based approach will create new instances and you will not be modifying the same array. They are a bit slow. Also if your array objects have other functions and symbols as a property, this will not be the best solution (They are not valid JSON values).

    If you are up for using a module you can use lodash. Import it and use

    DB.query().then((res) => { Questions = _.clondeDeep(res); 
    Reponses = _.clondeDeep(res); console.log(Reponses[0].sousquestions)})
    

    You can make your own function too.