I am using Mobx in my react app for global state. It has been working fantastic and exactly as expected until now. I am storing the mouse position in an SVG element in the store and hoping to utilize this state in a number of components. I can tell the state is changing correctly by logging inside the store, but for some reason my CrossHairs component is not re-rendering despite being wrapped in an observer HOC and featuring dereferenced store values. Any help would be much appreciated.
Store:
import PropTypes from 'prop-types';
import React, { createContext, useContext } from 'react';
import { webSocket } from 'rxjs/webSocket';
import { makeAutoObservable } from 'mobx';
import { PriceDataStore } from './_priceDataStore';
import { groupByFunction } from './utils/rxjs/groupByFunction';
import { TradePlanStore } from './_tradePlanStore';
export class WebsocketStore {
websocketSubject = webSocket('ws://localhost:8080/socket');
chartSubject;
priceDataStore;
tradePlanStore;
mouseCoordinates;
constructor() {
makeAutoObservable(this);
this.priceDataStore = new PriceDataStore(this);
this.tradePlanStore = new TradePlanStore(this);
this.chartSubject = groupByFunction(
'messageType',
'getChart',
this.websocketSubject
);
this.mouseCoordinates = {
x: 0,
y: 0,
};
}
sendWebsocketMessage = (msg) => {
this.websocketSubject.next(msg);
};
updateCoordinates = (coordinates) => {
this.mouseCoordinates = { x: coordinates[0], y: coordinates[1] };
};
}
const WebsocketContext = createContext(null);
export const useWebsocketStore = () => useContext(WebsocketContext);
export const WebSocketProvider = ({ store, children }) => {
return (
<WebsocketContext.Provider value={store}>
{children}
</WebsocketContext.Provider>
);
};
WebSocketProvider.propTypes = {
children: PropTypes.any,
store: PropTypes.any,
};
Place where state is being changed, this seems to be working:
const websocketStore = useWebsocketStore();
useEffect(() => {
select(zoomRef.current)
.on('mouseenter', () => {
setShowCrossHairs(true);
})
.on('mousemove', (event) => {
const coordinates = pointer(event);
websocketStore.updateCoordinates(coordinates);
})
.on('mouseleave', () => {
setShowCrossHairs(false);
});
}, [websocketStore.updateCoordinates]);
Component that is not triggered to re-render on mouseCoordinates state change in store despite being wrapped in observer and dereferencing mouseCoordinates values.
import PropTypes from 'prop-types';
import React, { useEffect } from 'react';
import { select, pointer } from 'd3';
import { colors } from '../../../../../../colorVars';
import { useWebsocketStore } from '../../../../../../stores/websocketStore/websocketStore';
import { observer } from 'mobx-react-lite';
const ChartCrossHairs = observer(({
size,
bottomPadding,
showCrossHairs,
}) => {
const websocketStore = useWebsocketStore();
const x = websocketStore.mouseCoordinates.x;
const y = websocketStore.mouseCoordinates.y;
return (
<g>
{showCrossHairs && (
<>
<line
strokeDasharray="1, 1"
x1={0}
x2={size}
y1={y}
y2={y}
stroke={colors.white}
/>
<line
strokeDasharray="1, 1"
y1={0}
y2={size + bottomPadding}
x1={x}
x2={x}
stroke={colors.white}
/>
</>
)}
</g>
);
});