I have a React.js application where I have a useContext
` where I make a GET
` request and also use a socket io to receive the change I tried to make in the server with the request. In a nutshell, I am requesting a change in the state of a property called mode
. Once the request is made, the backend receives it, applies some logic and returns me an OK if the mode change was successful or Error if not. If OK the socket io will send me on a topic the new updated mode. I pass this mode from the useContext to the component I need it to be at. I use an useEffect
` to sync the value I received from the server with my component's local mode and based on that I do animations but those animations do not execute correctly because the component rerenders on mode change so basically at the end I do receive the new updated mode from the server, it starts doing the animation for less than a second and then it stops because it rerenders, after the rerender is finished, i see myself with the new mode in place but I did not see the animation happening. Why is that? I figure it has to do with synchronization of the server and local state but I am not sure why it does not work the way I do it.
So here Is what I have done with my code.
First, the `useContext` code:
//server state
const [serverMode, setServerMode] = useState('Locked');
async function sendCommandRequest(command) {
console.log(endpoint);
console.log(serviceName);
console.log(command);
const url = `${endpoint}/?service=${serviceName}&command=${encodeURIComponent(JSON.stringify(command))}`;
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
};
const response = await fetch(url, options);
if (!response.ok) {
console.warn(`Sending command to ${serviceName} was not successful!`);
throw new Error('Network response was not ok');
}
return response.json();
}
async function commandVesselMaster(command) {
try {
console.log('Sending a command to Vessel Master', command)
const data = await sendCommandRequest(command);
if (command.name === 'Move') {
handleMoveCommand(data, command);
} else if (command.name === 'ChangeMode') {
handleChangeModeCommand(data);
} else if (command.name === 'GetMode') {
handleGetModeCommand(data);
}
} catch (error) {
console.error(`There was a problem with sending this command to the ${serviceName}:`, error);
}
}
useEffect(() => {
socket.current = io('http://127.0.0.1:5000/notifier', {
reconnection: false,
reconnectionAttempts: 1,
});
// Your event handlers, similar to what you have in BluetoothSetting component
const eventHandlers = {
ModeChange: data => {
const { mode } = data;
setServerMode(mode);
console.log("MODE RECEIVED FROM SERVER NOTIFIER ", mode);
},
}
Object.keys(eventHandlers).forEach(event => socket.current.on(event, eventHandlers[event]));
return () => {
if (socket.current) {
socket.current.close();
}
}
}, []);
Here is my component page where I use the useContext:
const [activeMode, setActiveMode] = useState(null);
useEffect(() => {
if (serverMode != null && activeMode != null && serverMode !== activeMode.charAt(0).toUpperCase() + activeMode.slice(1)) {
const mode = serverMode.toLowerCase();
setActiveMode(mode);
}
}, [serverMode, activeMode]);