Reputation: 1955
I use a reducer to update this state :
const [playlist, dispatch] = useReducer(jspfReducer,new playlistModel());
It uses my playlistModel
class, which is just a wrapper that adds some methods to manipulate easily my data - I need it.
I want to update the state, but avoid as much possible unecessary renders.
So when calling the reducer case UPDATE_JSPF_TRACK; I update only the matching track of the playlistModel
track array.
function jspfReducer(state, action){
switch (action.type) {
case 'UPDATE_JSPF_TRACK':
const [index,jspf] = action.payload;
//update only that single track.
const newTracks = state.track.map(
(track, i) => i === index ? new trackModel(jspf) : track
);
const newState = Object.assign(
state,
{
track:newTracks
}
);
//my object value is correctly updated here :
console.log("NEW STATE",newState);
return newState;
break;
}
};
The value logged in the console is correctly updated.
But in my provider, the state update is not detected:
export function PlaylistProvider({children}){
const [playlist, dispatch] = useReducer(jspfReducer,new playlistModel());
//when state updates
useEffect(()=>{
console.log("PLAYLIST HAS BEEN UPDATED!!!",playlist);//does not fire
},[playlist])
What is wrong and how could I fix this ? Thanks !
Upvotes: 0
Views: 323
Reputation: 10873
You'll need to create a new object for the state changes to be detected:
const newState = Object.assign(
{},
state,
{
track: newTracks,
},
);
or
const newState = { ...state, track: newTracks };
The way React works is it detects if the state objects have different referential equality, which basically means that if you only modify an object's attributes, it will still be considered the same object for the purposes of rendering. To trigger state change effect you'll need to create a new object.
Upvotes: 1