1

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>         
        )
    }
}

3

2 Answers 2

4

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),
);
Sign up to request clarification or add additional context in comments.

Comments

1

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))

1 Comment

Thanks Siraj, How can I forget this.Silly mistake.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.