minus.273
minus.273

Reputation: 777

Previous and current state are equal in componentDidUpdate

In a dashboard for each module its layout data (using react-grid-layout) is stored separately from the module data and each of them is stored in a database. Current module data and layout data are stored in the Dashboard component state. I am trying to call separate axios POST requests inside componentDidMount() whenever the previous state of the modules or the layouts differ from the current ones in order to save the changes in the database. But with debugging and logging, I see that prevState equals this.state.

Here are the methods that change the related states and the componentDidMount() method:

componentDidUpdate(prevProps, prevState) {
// JSON.stringify comparison for proof of concept since the order does not change
        if(JSON.stringify(prevState.modules) !== JSON.stringify(this.state.modules))
            API.post('Adminusers/StoreUserModuleData', "module_data=" + JSON.stringify(this.state.modules))
                        .then((res) => console.log(res))
                        .catch(err => {throw new Error(err)});
        if(JSON.stringify(prevState.layouts) !== JSON.stringify(this.state.layouts))
            API.post('Adminusers/StoreAdminUserLayouts', "layouts=" + JSON.stringify(this.state.layouts))
                        .then((res) => console.log(res))
                        .catch(err => {throw new Error(err)});  
    }

addNewModuleInLayout(moduleData) {

        let newLayout = this.state.layouts;
        let newModule = this.state.modules;

        for (let key in newLayout) {
            if (newLayout.hasOwnProperty(key)) {
                newLayout[key].push({
                    i: moduleData.type,
                    x: (newLayout[key].length * 1) % 3,
                    y: Infinity,
                    w: 1,
                    h: 5
                });
            }
        }

        newModule.push(moduleData);

        this.setState({layouts: newLayout, modules: newModule})
    }

removeModule(layoutId, type) {
        let newLayout = this.state.layouts;
        let newModule = this.state.modules;

        for (let key in newLayout)
            newLayout[key] = newLayout[key].filter(item => { return item.i !== layoutId })

        newModule = newModule.filter(item => {return item.type != type}); 

        this.setState({ modules: newModule, layouts: newLayout });
    }

An example of a module data and layout data for a certain module would be:

// layouts
{
 "md": [{ i: "current-user", x: 0, y: 0, w: 3, h: 5, isDraggable: false, isResizable: true }],
 "lg": [{ i: "current-user", x: 0, y: 0, w: 3, h: 5, isDraggable: false, isResizable: true }],
 "sm": [{ i: "current-user", x: 0, y: 0, w: 3, h: 5, isDraggable: false, isResizable: true }],
 "xs": [{ i: "current-user", x: 0, y: 0, w: 3, h: 5, isDraggable: false, isResizable: true }]
}

// module data
[{ type: "current-user", content: " ", title: "Current User Module" }]

Could anyone guide on what am I doing wrong here that both states are equal?

Upvotes: 2

Views: 789

Answers (1)

Michael Russo
Michael Russo

Reputation: 71

try updating your array declarations in both addNewModuleInLayout and removeModule to

const newLayout = { ...this.state.layouts }; // from let newLayout = this.state.layouts
const newModule = [...this.state.modules]; // from let newModule = this.state.modules

in cDM you don't create a "new" copy of your module/layout arrays on state, but rather reference the arrays directly. when you update the arrays you actually mutate your state, so when you diff prevState with this.state the stringified versions are equal.

this won't deeply copy your layouts object though so you will run into the same issue when pushing to your layout arrays. you might be able to get around this by creating a new array when updating a layout instead of pushing

newLayout[key] = [
 ...newLayout[key], 
 {
   i: moduleData.type,
   x: (newLayout[key].length * 1) % 3,
   y: Infinity,
   w: 1,
   h: 5
 }
]; // from newLayout[key].push({DATA}); in addNewModuleInLayout

since you use filter in removeModule you should be good there

Upvotes: 2

Related Questions