I have a project that sends values to a server when the state changes via websocket and i'm using redux-toolkit and I have a state like this
const initialState = {
exposure: false,
whiteBalance: false,
shutterSpeed: 1,
iso: 50,
temperature : 5500,
tint : 0,
brightness: { checked: false, value: 0 },
hue: { checked: false, value: 0 },
saturation: { checked: false, value: 0 },
vibrance: { checked: false, value: 0 },
contrast: { checked: false, value: 0 },
gamma: { checked: false, value: 0 },
sharpness: { checked: false, value: 0 },
};
const imageAdjustmentsSlice = createSlice({
name: "imageAdjustments",
initialState,
reducers: {
changeIso: (state, action: PayloadAction<number>): void => {
state.iso = action.payload;
},
changeTemperature: (state,action: PayloadAction<number>): void => {
state.temperature = action.payload;
},
changeTint: (state,action: PayloadAction<number>): void => {
state.tint = action.payload;
},
// and other reducers
}
});
const store = configureStore({
reducer: {
imgAdjustments:imageAdjustmentsSlice.reducer,
},
});
const WSController: React.FC = () => {
const videoStore = useAppSelector((state) => state.imgAdjustments);
const { sendMessage } = useWebSocket("ws://localhost:3000");
React.useEffect(() => {
// i want to send the changed value only not the whole state.
sendMessage(JSON.stringify(videoStore));
}, [videoStore ]);
return <></>
}
When videoStore changes i want to send the changed values to server. I want to know which value changes when the state changes. E.g. i changed iso value in somewhere using dispatch. I just want to get the changed value which is iso. Like this :
const changedValue = getChangedValue(state) // returns { iso : 200 }
Is there function/hook or another way to do this ? Or should i reconfigure redux?
There's no "built-in" React or React-Redux/Redux-Toolkit hook for this behavior/logic so you'd need to implement it yourself. I'd suggest implementing a custom React hook that can compute the difference between a current and previous object value.
Example:
import { useEffect, useRef } from "react";
// Typical "usePrevious" value hook recipe
const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
};
const useObjectDiff = (current) => {
const previous = usePrevious(current);
const diff = {};
if (current && previous) {
Object.entries(current).forEach(([key, value]) => {
if (previous[key] !== value) {
diff[key] = value;
}
});
}
return Object.keys(diff).length ? diff : null;
};
Demo:
Usage:
const WSController = () => {
const videoStore = useAppSelector((state) => state.imgAdjustments);
const { sendMessage } = useWebSocket("ws://localhost:3000");
const videoStoreDiff = useObjectDiff(videoStore);
React.useEffect(() => {
if (videoStoreDiff) {
sendMessage(JSON.stringify(videoStore));
}
}, [videoStoreDiff]);
return (
...
);
}