MESDOUR
MESDOUR

Reputation: 19

React : why state change when try to change it in immutable way , before calling the setState

When I try to change state immutable way in React, it is changing the state before I call setstate, which confused me for 3 days now.

This is the method I call in the onClick event:

share = (indexFolder) => {
    console.log(this.state.folderInfo);
    const updateFolderInfo = [...this.state.folderInfo];
    updateFolderInfo[indexFolder].isProcessing = false; 

    //state**is already changed**strong text** when console **
    console.log(this.state.folderInfo);

    this.setState({
            folderInfo : updateFolderInfo,
    })
    // the setState call do not take effect here 
}

This is where the method is executed:

<Folder key={folder._id}
        sharing={this.state.folderIsProcessing}
        folder={folder} 
        delete={() => this.delete(index)}
        share={() => this.share(index)} />
//I'm passing share function as props in here ^ , and use it on 
//click event in the Folder component . 

Any suggestions why this is happening?

Upvotes: 1

Views: 106

Answers (3)

MinimumViablePerson
MinimumViablePerson

Reputation: 81

The problem here is that by doing const updateFolderInfo = [...this.state.folderInfo]; you are effectively making a shallow copy of folderInfo.

What that means is that, if you modify any item inside updateFolderInfo that is an object or an array, you will also be modifying the same object/array inside the original folderInfo array.

Assuming folderInfo has only JSON inside, here's a potential solution using JSON.stringify and JSON.parse to create a deep copy:

share = indexFolder => {
  const updatedFolderInfo = JSON.parse(JSON.stringify(this.state.folderInfo));
  updatedFolderInfo[indexFolder].isProcessing = false; 

  this.setState({ folderInfo : updatedFolderInfo });
}

Here's a tiny example of show you what you are currently doing in a simplified way:

array1 = [{id: 1}, {id: 2}, {id: 3}]
array2 = [...array1]

array2[0].id = 100

array2
// [{id: 100}, {id: 2}, {id: 3}]

array1
// [{id: 100}, {id: 2}, {id: 3}]

You can find more info on shallow vs deep cloning here.

Upvotes: 1

Azamat Zorkanov
Azamat Zorkanov

Reputation: 819

Too few information provided, but try to use setState in other way:

share = (indexFolder) => {
  this.setState((prevState) => {
        const updateFolderInfo = [...prevState.folderInfo];
        updateFolderInfo[indexFolder].isProcessing = false; 
        return { 
            folderInfo : updateFolderInfo
        }
  }) 
}

About async nature of setState: https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3

Upvotes: 0

Anshul Bansal
Anshul Bansal

Reputation: 1893

You are already binding the function to the scope above. Try changing it like this.

share = (indexFolder) => {
      console.log(this.state.folderInfo);
      const updateFolderInfo = [...this.state.folderInfo];
      updateFolderInfo[indexFolder].isProcessing = false; 
      //state**is already changed**strong text** when console **
       console.log(this.state.folderInfo);
      this.setState({
            folderInfo : updateFolderInfo,
      })
      // the setState call do not take effect here 
    }

<Folder  key={folder._id}
                                sharing={this.state.folderIsProcessing}
                                folder={folder} 
                                delete={this.delete(index)}
                                share={this.share(index)}
        />

Upvotes: 0

Related Questions