1

I am dynamically adding and removing Dropdowns based on the index of the array. I am setting the index using. When adding or removing a dropdown, I increment and decrement that index. The goal would be an array that looks something like this:

[
  { index: 0, type: "facebook" },
  { index: 1, type: "instagram" }
]

The problem is when I add a new dropdown, the index is incrementing by 2 or 3 instead of 1, resulting in the following output.

[
  { index: 0, type: "facebook" },
  { index: 2, type: "instagram" }
]

Here is the code for my component:

class SocialProfileComponent extends Component {
    constructor(props) {
        super(props);
        let index = 0;
        this.state = {
            options: [ 
                {value: 'email', label: 'Email'},
                {value: 'instagram', label: 'Instagram'},
                {value: 'linkedin', label: 'Linkedin'},
                {value: 'pinterest', label: 'Pinterest'},
                {value: 'skype', label: 'Skype'},
                {value: 'tiktok', label: 'TikTok'},
                {value: 'tumblr', label: 'Tumblr'},
                {value: 'twitter', label: 'Twitter'},
                {value: 'whatsapp', label: 'WhatsApp'},
                {value: 'wordpress', label: 'Wordpress'},
                {value: 'youtube', label: 'Youtube'},
                {value: 'other', label: 'Other'},
                
            ],
            socialDetails: [
                {
                    index: index,
                    type: "",
                    link: "",
                    
                }
            ]
        };
    }

    addNewRow = (e) => {
        
        this.setState(prevState => ({
            socialDetails: [
                ...prevState.socialDetails,
                {
                    index: index++,
                    type: "",
                    link: "",
                }
            ]
        }));
    }

    deleteRow = (index) => {
        this.setState({
            socialDetails: this.state.socialDetails.filter(
                (s) => index !== s.index
            )
        })
    }

    clickOnDelete(record) {
        this.setState({
            socialDetails: this.state.socialDetails.filter(r => r!==record)
        })
    }

    componentDidMount() {

    }

    render = () => {
        let {socialDetails, options} = this.state;
        const {onInputChange} = this.props;
        return (
            <>
                <SocialProfile 
                    label={`Social profiles`}
                    addRow={this.addNewRow}
                    deleteRow={this.deleteRow}
                    socialDetails={socialDetails}
                    options={options}
                    onInputChange={onInputChange}
                    formKey={'socialprofiles'}
                    createKeyValue={this.createNewKeyValuePair}
                    placeholder={'Select'}
                />
            </>
        )
    }
}

Code Sandbox

0

1 Answer 1

1

The behavior you are experiencing where the index increases by 2 or 3 is a result of React strict mode. In addition to other things, strict mode helps detect unexpected side effects to help you prepare your app for the upcoming concurrent mode feature. In concurrent mode, React will break up rendering into smaller chunks pausing and resuming work as necessary. This means that render phase lifecycle methods can be run more than once.

To help you prepare for this upcoming behavior of concurrent mode, strict mode will intentionally invoke render phase lifecycles twice to identify potential side effects. State updater functions are one instance of this, meaning that calling index++ in your state updater function will be run twice in strict mode.

The easiest solution would be to simply assign the new index to a variable before calling this.setState so that your state updater function is idempotent and can be called more than once.

addNewRow = (e) => {
  const newIndex = ++this.index

  this.setState((prevState) => ({
    socialDetails: [
      ...prevState.socialDetails,
      {
        index: newIndex,
        type: "",
        link: ""
      }
    ]
  }));
};
Sign up to request clarification or add additional context in comments.

1 Comment

Beautiful explanation! Thanks for clarifying about the render method mate! :)

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.