Ashwani Garg
Ashwani Garg

Reputation: 1527

react setstate is not replacing the array with new array

It's about setState of an array.

React setstate is not replacing the array with new array

You can see that, I have customFieldsComponents in the constructor state.

In the addCustomField() function, I'm adding some elements in the array with the unique keys.

Now,In the removeCustomField() function, when I want to remove an element from the array, by setting new array of the filtered elements, its not replacing the customFieldsComponents array.

The problem is in the removeCustomField() function.

https://gist.github.com/akgarg007/ba8ade35b64b423def767fdfda263744

If you see the gist, I'm having issues on line number 98.


import React, { Component } from 'react';

// Import Custom Components
import TextField from '../CustomFieldComponents/TextField';
import DateField from '../CustomFieldComponents/DateField';
import RadioField from '../CustomFieldComponents/RadioField';

export const CustomFieldContext = React.createContext();

export class CustomFieldProvider extends Component {
    constructor(props) {
        super(props)
        this.state = {
            //  PhoneFieldCounter: 1,
            //  phoneComponents: [],
             customFieldSelected:'',
             customFieldsArray:[],
             customFieldsComponents:[],
        }
        this.addCustomField = this.addCustomField.bind(this);
        this.removeCustomField = this.removeCustomField.bind(this);
        this.handleCustomFieldChange = this.handleCustomFieldChange.bind(this);
    }
    addCustomField(){
        /***
         * Add all selected fields in the customFieldsArray array.
         * If custom field is already selected, it can't be selected again.
         * 
         * We can try to update the select dropdown list later on.  
         */    
        if(this.state.customFieldSelected.length == 0){
             // If no custom field selected!
            alert('Please select a field!');
            return NULL;
        }else if(this.state.customFieldSelected == 'Select'){
             // If no custom field selected!
            alert('Please select a field!');
            return NULL;
        }else{
            // check if field is already inserted in the addray or not
            var n = this.state.customFieldsArray.includes(this.state.customFieldSelected);    
            if(n != true){
                console.log(this.state.customFieldSelected);
                this.state.customFieldsArray.push(this.state.customFieldSelected);
            }else{
                // console.log(this.state.customFieldsArray);
                // console.log('field already selected, select another');
                alert('This field already selected, select another');
                return NULL;
            }
            // If selected field is a Text, then add new TextField in the custom Fields array
            if(
                this.state.customFieldSelected == 'PersonalID' ||
                this.state.customFieldSelected == 'Website' || 
                this.state.customFieldSelected == 'LinkedIn' ||
                this.state.customFieldSelected == 'Facebook' || 
                this.state.customFieldSelected == 'Twitter' || 
                this.state.customFieldSelected == 'Skype'
            ){
                var newField = (
                    <TextField key={this.state.customFieldSelected}  fieldName = {this.state.customFieldSelected} />
                );

            }else if(this.state.customFieldSelected == 'Birth Date'){
                var newField = (
                    <DateField key={this.state.customFieldSelected}  fieldName = {this.state.customFieldSelected} />
                );
            }
            else if(this.state.customFieldSelected == 'Gender'){
                const fieldNames = ['male','female'];
                var newField = (
                    <RadioField key={this.state.customFieldSelected}  fieldName = {this.state.customFieldSelected} fieldNames={fieldNames}  />
                );
            }
            else if(this.state.customFieldSelected == 'Decision Maker'){
                const fieldNames = ['yes','no'];
                var newField = (
                    <RadioField key={this.state.customFieldSelected}  fieldName = {this.state.customFieldSelected} 
                    fieldNames={fieldNames}  />
                );
            }
            this.setState(prevState => ({
                customFieldsComponents: [...prevState.customFieldsComponents, newField]
            }))
            // If selected field is a Textarea, then add new TextareaField in the custom Fields array
            // If selected field is a Radio, then add new RadioField in the custom Fields array
            // If selected field is a Dropdown, then add new DropdownField in the custom Fields array
        }

    }

    removeCustomField(fieldName){
        // First filter the field you want to remove from the array.
        // Then replace the old array with the new updated array. 

        var updatedCustomFieldComponents = this.state.customFieldsComponents.filter(element => element.key != fieldName);

        this.setState({ customFieldsComponents: [] }, console.log(this.state.customFieldsComponents))
        // this.setState({ customFieldsComponents: updatedCustomFieldComponents }, console.log(this.state.customFieldsComponents))
    }

    handleCustomFieldChange(field){
        this.setState({
            customFieldSelected: field
        });
    }

    render() {

        return (
            <CustomFieldContext.Provider 
                value={{
                    state:this.state,

                    addCustomField: this.addCustomField,
                    removeCustomField:(fieldName)=>{
                        this.removeCustomField(fieldName)
                    },
                    handleCustomFieldChange: (e)=>{
                        this.handleCustomFieldChange(e.target.value)
                    }
                }}
            >
                {this.props.children}
            </CustomFieldContext.Provider>         
        )
    }
}

Upvotes: 1

Views: 1715

Answers (2)

Siraj Alam
Siraj Alam

Reputation: 10085

The second parameter of the setState is a callback, but you're just calling the console.log

change this

 this.setState({customFieldsComponents[]},console.log(this.state.customFieldsComponents))

to this

 this.setState({customFieldsComponents[]},() => console.log(this.state.customFieldsComponents))

Upvotes: 1

Drew Reese
Drew Reese

Reputation: 203457

The issue is you aren't using the setState callback correctly, it should be a function. As you've done, the log would fire immediately with the current state value, before it's been updated.

this.setState(
  { customFieldsComponents: [] }, 
  () => console.log(this.state.customFieldsComponents),
);

and

this.setState(
  { customFieldsComponents: updatedCustomFieldComponents },
  () => console.log(this.state.customFieldsComponents),
);

Upvotes: 4

Related Questions