Home > database >  React - refresh in UI after deleting item in array not working for first click
React - refresh in UI after deleting item in array not working for first click

Time:08-17

I am facing a weird situation while working with React. We have a custom control in Dynamics 365 in what we use a dynamic inputs generated via Add button and removing with Delete button. And since the labels of the inputs include "1st", "2nd" etc., we need to re-render the correct labels. Example: If there are up to 3 inputs "1st Renewal", "2nd Renewal" and "3rd Renewal", when user deletes the 2nd input, the 3rd should refresh to "2nd Renewal".

Behind the scenes, we work with an array of numbers, from where we generate Fluent UI elements.

const getIndexationPeriodPrefixFor = (numberPrefix: number) => {
        return `${getNumberPrefix(numberPrefix)} Renewal`;
    }

    const generateDynamicContractedValues = () : IContractedValue[] => {
        let dynamicValues = new Array<IContractedValue>();
        props.contracted_prices.forEach((value, index) => {
            dynamicValues.push(new ContractedValue(getIndexationPeriodPrefixFor(index   1), value));
        });
        if (dynamicValues.length == 0) {
            // Create initial 1st Renewal input for new Contracted indexation type.
            dynamicValues.push(new ContractedValue("1st Renewal", null));
        }
        return dynamicValues;
    };
  const dynamicContractedValuesElements =
        dynamicContractedValues.map((value, index) => {        
            return {
                renewalPeriod: value.renewalPeriod,
                renewalFragment: <>                   
                    <TooltipHost content="Renewal price agreed with the purchaser for the renewal period, excluded from indexation.">
                        <TextField required={index == 0} disabled={shouldBeInputDisabled}
                            type="number" id={`Input-Renewal-${index 1}`}
                            value={value.renewalPrice?.toPrecision()}
                            onKeyDown={e => ValidationService.PreventMinusSign(e)}
                            onChange={e => updateRenewal(e, index)}
                            suffix={props.currency.name}></TextField></TooltipHost><ActionButton id={`Btn-Remove-Renewal-${index 1}`} iconProps={{ iconName: "Delete" }} onClick={() => { removeRenewalLine(index) }} disabled={index < 1} hidden={shouldBeInputDisabled || index < 1}></ActionButton>
                    {doesRenewalPriceHaveUnexpectedValue && unexpectedPriceWarning}</>
            }
        })
    
    const removeRenewalLine = (index: number) => {             
        let newContractedPrices = [...contractedPrices];
        newContractedPrices.splice(index, 1);
        setContractedPrices(newContractedPrices);
        let newDynamics = generateDynamicContractedValues();
        // We want to reload the number prefixes, when the user deletes a contracted period.
        // Example: When user deletes 2nd Renewal, the 3rd Renewal should change to 2nd Renewal.    
        setDynamicContractedValues(newDynamics);              
    }

We generate the UI elements via the contracted_prices array with generateDynamicContractedValues method.

The problem is with the line

<ActionButton id={`Btn-Remove-Renewal-${index 1}`} iconProps={{ iconName: "Delete" }} onClick={() => { removeRenewalLine(index) }}

Specifically with the removeRenewalLine(index) method - it's not causing any change in UI for the first click of the user. When you click delete, the array behind the control is changed, but the input is not being deleted and then the prefixes recalculated -> just for the first click. From the second click it works just as I wanted.

Any ideas please? Thank you

CodePudding user response:

Store the array in a useState. If it's just a variable, it's not reactive. Thus the DOM will not react to a change of the variable.

  • Related