broccoli_rob
broccoli_rob

Reputation: 550

React/Redux: componentDidUpdate not firing consistently

I have nested arrays in my props, and the user can re-order the second-level array by dragging and dropping column. I (using redux) make a shallow copy of getState's outer array, do the re-ordering (through re-assignment of array objects based on index), and return the new array to the state (using spread operator in my reducer). However, componentDidUpdate is not called if this ordering is the first thing I do after page load. If I take other actions that update the props/state, and then attempt to re-order, the ordering works fine and componentDidUpdate is called.

In the former situation, where ordering is the first thing I try to do after page load/refresh, the render function is hit (with the properly re-ordered props) but the DOM never updates, presumably because redux does not recognize a state change?

It just seems like some other props change (even if unrelated to arrays) "wakes up" redux or connect and allows it to recognize changes.

Here's where I copy, dispatch and then release the updated state in the reducer:

in actionCreator method:

...
const newProjects = getState().tracker.projects.slice().map(p => {
    if (p.innerArray) {
        const from = p.innerArray[draggedId-1];
        const to = p.innerArray[droppedId-1];
        p.innerArray[draggedId - 1] = { ...to, order: draggedId };
        p.innerArray[droppedId - 1] = { ...from, order: droppedId };
    }
    return p;
})                
dispatch({ type: 'RECEIVE_FIELD_UPDATE', projects: newProjects, message: "Sorted" });

reducer:

case 'RECEIVE_FIELD_UPDATE':
        return {
            ...state,
            projects: action.projects,
            message: action.message
        }

As you can see, I'm not mutating state in the reducer or doing other anti-pattern things (as far as I'm aware).

FWIW, the "Sorted" value on message property seems to get through whether or not componentDidUpdate is hit (I have a modal that pops up with the message to confirm).

Any pointers or related documentation would be helpful; I've been reading all I can find, including other StackOverflow posts, but to no avail.

UPDATE Solved the issue, it did have to do with redux not diff-ing the properties but not because of what I expected, read below if interested.

Upvotes: 0

Views: 1595

Answers (2)

broccoli_rob
broccoli_rob

Reputation: 550

Figured this out, and per usual I was looking in the wrong place.

The issue was that my conditional check on page load to prevent re-loading of already stored data was preventing any dispatches from firing. When I looked in the reducer, the sub-arrays of the projects were identical after dragging, because the state had not been previously connected yet. I thought a hard refresh would cause a full re-load but apparently I need to read more about how redux stores data and how to refresh that.

Anyways, fixing this condition so that I get new data on page load fixed the issue and componentDidUpdate is now being triggered consistently.

Upvotes: 1

seanulus
seanulus

Reputation: 885

When updating state in a reducer in an array format, I've had to spread state again in order for updates to happen and keep from mutating.

case 'RECEIVE_FIELD_UPDATE':
        return {
            ...state,
            projects: ...state, ...action.projects,
            message: action.message
        }

or...

case 'RECEIVE_FIELD_UPDATE':
         return {
             ...state,
             projects: [...state, ...action.projects],
             message: action.message
            }

Depending on the format. Hope that helps.

Upvotes: 0

Related Questions