我有下面这段代码(在reactJS中)。基本上它是小部件的一部分,每次数据更新时,“GraphInfo 已更改:”和“GraphData 已更改:”意味着 uhsestate 和 useMemo 被忽略。我基本上想从带有 graphInfo 变量的数据中导出不同的数据。
const BaseGraphOverTime = ({
module_key,
data,
graph_type,
y,
strike,
opt_type,
}) => {
const [graphData, setGraphData] = useState(data);
const { globalState } = useGlobal();
const graphInfo = useMemo(
() => ({
y: y,
strike: strike,
opt_type: opt_type,
ticker: globalState.ticker,
expiration_date: globalState.expiration_date,
}),
[y, strike, opt_type, globalState.ticker, globalState.expiration_date]
);
useEffect(() => {
console.log(
"GraphInfo changed:",
y,
strike,
opt_type,
globalState.ticker,
globalState.expiration_date
);
}, [y, strike, opt_type, globalState.ticker, globalState.expiration_date]);
useEffect(() => {
console.log("GraphData changed:", graphData);
}, [graphData]);
return null;
};
export default BaseGraphOverTime;
我尝试将 useMemo 和 useState 相互更改,但没有任何帮助。我什至使用数据的 useState 设置父组件。
根据要求,这里有更多代码和更多说明。 数据是通过 websocket 接收的(数据被接收并从它们的 id 发送到不同的小部件)。 MemoizedWidget 和 Widget 渲染正确的组件(此处为 BaseGraphOverTime)
const { socket, data, sendMessage, ws_connected } = useWebSocket("wss://.........");
const widgetDataReducer = (state, action) => {
switch (action.type) {
case "UPDATE_WIDGET_DATA":
const { dashboard_item_id, newData } = action.payload;
if (state[dashboard_item_id] && state[dashboard_item_id] === newData) {
return state; // No change, so return current state
}
return {
...state,
[dashboard_item_id]: newData,
};
default:
return state;
}
};
const [widgetData, dispatch] = useReducer(widgetDataReducer, {});
useEffect(() => {
if (data) {
console.log("Data received from WebSocket:", data);
// Here you can set data to global state or handle it as needed
if (data.type === "stream") {
// We distribute the data
dispatch({
type: "UPDATE_WIDGET_DATA",
payload: {
dashboard_item_id: data.dashboard_item_id,
newData: data.data,
},
});
}
}
}, [data]);
{...}
return (...
{layout.map((item) => (
<div className="widget" key={item.i.key} data-grid={item}>
<MemoizedWidgetComponent
viewUnlocked={viewUnlocked}
widget_type={item.i.type}
module_key={item.i.key}
onRemoveWidget={handleRemoveWidget}
data={widgetData[item.i.key]}
/>
</div>
))}
...)
这是小部件:
const WidgetComponent = ({
viewUnlocked,
module_key,
widget_type,
onRemoveWidget,
data,
}) => {
const widget_info = WidgetInformation[widget_type];
const [widgetInfo, setWidgetInfo] = useState({
x: "strike_price",
y: "open_interest",
graph_type: "line",
horizontal: false,
exposure_type: "net",
strike: null,
opt_type: "call",
});
const { globalState, setGlobalState } = useGlobal();
const Widget = () => {
const Component = widget_info.module;
if (!Component) {
console.log("Component not found");
return <div>Component not found</div>;
}
return (
<Component
module_key={module_key}
data={data}
{...widget_info.args}
{...widgetInfo}
/>
);
};
const BaseGraphEvolutionHead = (
...<FormControl variant="standard">
<NativeSelect
value={widgetInfo.opt_type}
onChange={(e) =>
setWidgetInfo({ ...widgetInfo, opt_type: e.target.value })
}
input={<CustomInput />}
inputProps={{
name: "opt_type",
id: "uncontrolled-native",
}}
>
<option value="call">Call</option>
<option value="put">Put</option>
</NativeSelect>
</FormControl>
...)
const HandleDiv = memo(() => {
const styleRef = useRef({
cursor: "default",
width: "calc(100% - 100px)",
});
useEffect(() => {
if (viewUnlocked) {
styleRef.current = { ...styleRef.current, cursor: "move" };
} else {
styleRef.current = { ...styleRef.current, cursor: "default" };
}
}, [viewUnlocked]);
return (
<div className="widget-header">
<Grid container rowSpacing={0} columnSpacing={0}>
<Grid item minWidth="40px" width="40px">
<CloseButton />
</Grid>
<Grid item className="handle" style={styleRef.current}>
<BaseGraphEvolutionHead
ticker={globalState.ticker}
expiration_date={globalState.expiration_date}
/>
</Grid>
<Grid item minWidth="40px" width="40px"></Grid>
</Grid>
</div>
);
});
return (
<Grid
container
spacing={0}
style={{ height: "100%", width: "100%", userSelect: "none" }}
direction="column"
>
<Grid item height="30px">
<HandleDiv />
</Grid>
<Grid
item
height="calc(100% - 30px)"
width="100%"
style={{ paddingBottom: "10px", overflow: "auto" }}
>
<div className="content">
<Widget />
</div>
</Grid>
</Grid>
);
};
const MemoizedWidgetComponent = memo(
({ module_key, widget_type, data, viewUnlocked, onRemoveWidget }) => {
return (
<WidgetComponent
viewUnlocked={viewUnlocked}
widget_type={widget_type}
module_key={module_key}
onRemoveWidget={onRemoveWidget}
data={data}
/>
);
},
(prevProps, nextProps) => {
// Log differences if the data objects are not equal
const dataChanged = !isEqual(prevProps.data, nextProps.data);
return (
prevProps.viewUnlocked === nextProps.viewUnlocked &&
prevProps.module_key === nextProps.module_key &&
prevProps.widget_type === nextProps.widget_type &&
!dataChanged
);
}
);
在 BaseGraphOverTime 中,我尝试将 useEffect 依赖项设置为: