我使用以下实现收到错误“超出最大更新深度”:
export type InstrumentDetailBaseState =
| BaseState
| {
type: 'success';
detail: InstrumentDetail;
};
export interface RealTimeInstruments {
[key: string]: InstrumentDetailBaseState;
}
export interface MarketsState {
details: RealTimeInstruments;
}
export const initialState: MarketsState = {
details: {},
};
const slice = createSlice({
name: '/markets',
initialState,
reducers: {
updateInstrumentDetail: (
state,
{ payload }: PayloadAction<UpdateInstrumentDetailRequest>,
) => {
const current = state.details[payload.key];
const detail = current.detail;
state.details[payload.key] = {
type: 'success',
detail: Lodash.merge({}, detail, payload.detail),
};
},
},
});
export const { updateInstrumentDetail } = slice.actions;
在我的操作文件中我有这个:
export const useUpdateInstrumentDetailAction = () => {
const dispatch = useAppDispatch();
return useCallback(
(request: UpdateInstrumentDetailRequest) => {
dispatch(updateInstrumentDetail(request));
},
[dispatch],
);
};
这是我的选择器实现:
export type AppSelector<Response, Request = null> = Selector<
MainAppState,
Response,
Request
>;
const instrumentDetails: AppSelector<RealTimeInstruments> = ({
marketsReducer,
}) => marketsReducer.details;
const instrumentDetailsKeyArgs: AppSelector<
string,
RealTimeInstrumentSelectorRequest
> = (_, { key }) => key;
const createDeepEqualSelector = createSelectorCreator(defaultMemoize, isEqual);
const createDetailItemSelector = () =>
createDeepEqualSelector(
instrumentDetails,
instrumentDetailsKeyArgs,
(details, key) => {
const current = details[key];
if (current?.type === 'success') {
return current.detail;
}
return undefined;
},
);
export function useRealTimeInstrumentDetail(
key: string,
defaultItem?: InstrumentDetail | undefined,
): InstrumentDetail | undefined {
const detailItemSelector = useMemo(createDetailItemSelector, []);
const selector = useCallback(
(state: BeTradingAppState) => detailItemSelector(state, { key }),
[key, detailItemSelector],
);
const item = useAppSelector(selector);
return useMemo(
() => Lodash.merge({}, defaultItem, item),
[defaultItem, item],
);
}
我使用 lightstreamer 套接字来收听股市更新。
const useLightstreamerClient = () => useContext(LightstreamerContext);
export const useLightStreamerSubscription = (
request: SubscriptionRequest,
listener: SubscriptionListener,
) => {
const client = useLightstreamerClient();
useEffect(() => {
const subscription = new Subscription(
request.mode,
request.items,
request.fields,
);
subscription.setRequestedSnapshot('yes');
subscription.addListener(listener);
client?.subscribe(subscription);
return () => {
client?.unsubscribe(subscription);
};
}, [client, request, listener]);
};
最后我使用这个自定义挂钩来生成订阅。
在这种情况下,当 lightstreamer 发送多个“刻度”或“更新”并且调用 onItemUpdate 函数时,系统会抛出下一个错误:
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
注意:当我说“多个”时,我的意思是每个订阅密钥每秒更新 1 到 100 次。
export const useRealTimeInstrumentSubscription = (
subscriptionKeys: string[],
) => {
const updateInstrument = useUpdateInstrumentDetailAction();
const subscriptionRequest = useMemo<SubscriptionRequest>(() => {
return {
mode: 'MERGE',
items: subscriptionKeys,
fields: [
'id',
'price',
'volume',
],
};
}, [subscriptionKeys]);
const subscriptionListener = useMemo<SubscriptionListener>(
() => ({
onItemUpdate: item => {
const id: string = item.getValue('id');
const priceValue = item.getValue('price');
const volumeValue = item.getValue('volume');;
const detail: RealTimeInstrumentDetail = {
price: parseNumber(priceValue),
volume: parseNumber(volumeValue),
};
updateInstrument({
key: id,
detail,
});
},
}),
[updateInstrument],
);
useLightStreamerSubscription(subscriptionRequest, subscriptionListener);
};
我使用这样的订阅:
在这种情况下,仪器阵列是静态的并且不处于状态。
const InstrumentsDataList: React.FC<{
readonly instruments: Instrument[];
}> = ({ instruments }) => {
const subscriptionKeys = useMemo(
() => instruments.map(({ instrument }) => instrument.subscriptionKey),
[instruments]
);
useRealTimeInstrumentSubscription(subscriptionKeys);
return (
<FlatList
style={styles.container}
data={instruments}
keyExtractor={({ instrument }) => instrument.uniqueKey}
renderItem={({ item }) => (
<InstrumentDataListItem
item={item}
/>
)}
/>
);
};
这是列表项:
const InstrumentDataListItem: React.FC<InstrumentDataListItemProps> = ({
item,
}) => {
const {
price,
spread,
posture,
variation: { unit, percentage },
} = useRealTimeInstrumentDetail(item.instrument.uniqueKey, item.detail);
return <View>...</View>;
};
export default InstrumentDataListItem;
即使我删除 FlatList,错误仍然存在。
const InstrumentsDataList: React.FC<{
readonly instruments: Instrument[];
}> = ({ instruments }) => {
const subscriptionKeys = useMemo(
() => instruments.map(({ instrument }) => instrument.subscriptionKey),
[instruments]
);
useRealTimeInstrumentSubscription(subscriptionKeys);
return (
<View/>
);
};
当调用“updateInstrument”操作时,调试器会跟踪“onItemUpdate”函数中“useRealTimeInstrumentSubscription”内的错误。
我在列表项内使用
useRealTimeInstrumentDetail
钩子以获得更好的性能。
选择器已被记忆,但错误仍然存在。