React custom hook spit Error " Error: Should have a queue. This is likely a bug in React. Please file an issue"
React custom hook spit Error " Error: Should have a queue. This is likely a bug in React. Please file an issue"
我有 React 组件,它需要从组件内部使用自定义的 React Hook。
但是,只有在启用功能切换时才应调用此挂钩。我知道这是一种反模式,因为它违反了这里的钩子规则:https://reactjs.org/docs/hooks-rules.html
所以我的组件文件大致是这样的结构:
const someFeatureToggle = useSomeFeatureToggleHook(React);
const callBackMethod = ()=>{
// doing the logic
}
const someRef1 = React.useRef();
const someOtherRef = React.useRef();
...
There are lots of useState( ) here
return (
JSX
)
自定义挂钩:
export default function myCustomizedHook(topics, messagesReceivedFn, subscriptionOptions = {}) {
if (!isValidTopics(topics)) {
throw new Error(`Topics arg is invalid - Arg ${JSON.stringify(topics)}`);
}
const [someSubTopics] = useState([topics].flat());
const context = useContext(SomeEventContext);
if (isUndefined(context)) {
throw new Error(`${customizedHook.name} must be used within SomeProvider`);
}
const { connectionStatus, connector } = context;
const isConnectorConnected = connector?.connected ?? false;
const isConnectorReconnecting = connector?.reconnecting ?? false;
const messageReceivedHandler = useCallback(
(receivedTopic, message) => {
if (subscribedTopics.some((topic) => matches(topic, receivedTopic))) {
messagesReceivedFn?.(receivedTopic, message);
}
},
[messagesReceivedFn, subscribedTopics]
);
useEffect(() => {
isConnectorConnected && connector?.on(CLIENT_EVENTS.MESSAGE, messageReceivedHandler);
return () => {
connector?.off(CLIENT_EVENTS.MESSAGE, messageReceivedHandler);
};
}, [messageReceivedHandler, connector, isConnectorConnected]);
useDeepCompareEffect(() => {
isConnectorConnected && connector.subscribe(subscribedTopics, subscriptionOptions);
return () => {
subscribedTopics && connector?.unsubscribe(subscribedTopics);
};
}, [connector, isConnectorConnected, subscribedTopics, subscriptionOptions]);
return { isConnected: isConnectorConnected, isReconnecting: isConnectorReconnecting, connectionStatus, subscribedTopics };
现在错误轨迹是这样的:
Uncaught Error: Should have a queue. This is likely a bug in React. Please file an issue.
at updateReducer (react-dom.development.js:15255:15)
at updateState (react-dom.development.js:15671:12)
at Object.useState (react-dom.development.js:16472:18)
at useState (react.development.js:1533:23)
at customizedHook (customizedHook.js:28:38)
at componentThatConsumeHook (componentThatConsumeHook.js:67:99)
at renderWithHooks (react-dom.development.js:15015:20)
at updateFunctionComponent (react-dom.development.js:17386:22)
at beginWork (react-dom.development.js:19093:18)
at HTMLUnknownElement.callCallback (react-dom.development.js:3942:16)
并且浏览器中的开发控制台出现此警告:
Warning: React has detected a change in the order of Hooks called by myComponent. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
Previous render Next render
------------------------------------------------------
1. useRef useRef
2. useState useState
3. useEffect useEffect
4. useRef useState
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
customizedHook的第28行指向下面这一行:
const [someSubTopics] = useState([topics].flat());
这是我在组件中使用钩子的方式:
const result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);
我在这里挠头,因为我不知道为什么会这样,任何想法或建议将不胜感激!!!!
那是因为你在条件内调用 hook。
const result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);
与
基本相同
let result = false
if (!!featureToggles.Flag){
result = customHook(arg1, callbackMethod);
}
来自 React 文档:
Don’t call Hooks inside loops, conditions, or nested functions.
您可以做的是将 featureToggles
传递到您的自定义挂钩中,然后在其中进行检查。
确保你的条件检查在你的挂钩底部,在每个挂钩调用下面。
// pass featureToggles here
export default function myCustomizedHook(featureToggles, topics, messagesReceivedFn, subscriptionOptions = {}) {
// your code here
useDeepCompareEffect(() => {
isConnectorConnected && connector.subscribe(subscribedTopics, subscriptionOptions);
return () => {
subscribedTopics && connector?.unsubscribe(subscribedTopics);
};
}, [connector, isConnectorConnected, subscribedTopics, subscriptionOptions]);
// make sure to do the check at the bottom, below every hook call
if (!!featureToggles.Flag) {
// handle this feature toggle
return null
}
return { isConnected: isConnectorConnected, isReconnecting: isConnectorReconnecting, connectionStatus, subscribedTopics };
我有 React 组件,它需要从组件内部使用自定义的 React Hook。
但是,只有在启用功能切换时才应调用此挂钩。我知道这是一种反模式,因为它违反了这里的钩子规则:https://reactjs.org/docs/hooks-rules.html
所以我的组件文件大致是这样的结构:
const someFeatureToggle = useSomeFeatureToggleHook(React);
const callBackMethod = ()=>{
// doing the logic
}
const someRef1 = React.useRef();
const someOtherRef = React.useRef();
...
There are lots of useState( ) here
return (
JSX
)
自定义挂钩:
export default function myCustomizedHook(topics, messagesReceivedFn, subscriptionOptions = {}) {
if (!isValidTopics(topics)) {
throw new Error(`Topics arg is invalid - Arg ${JSON.stringify(topics)}`);
}
const [someSubTopics] = useState([topics].flat());
const context = useContext(SomeEventContext);
if (isUndefined(context)) {
throw new Error(`${customizedHook.name} must be used within SomeProvider`);
}
const { connectionStatus, connector } = context;
const isConnectorConnected = connector?.connected ?? false;
const isConnectorReconnecting = connector?.reconnecting ?? false;
const messageReceivedHandler = useCallback(
(receivedTopic, message) => {
if (subscribedTopics.some((topic) => matches(topic, receivedTopic))) {
messagesReceivedFn?.(receivedTopic, message);
}
},
[messagesReceivedFn, subscribedTopics]
);
useEffect(() => {
isConnectorConnected && connector?.on(CLIENT_EVENTS.MESSAGE, messageReceivedHandler);
return () => {
connector?.off(CLIENT_EVENTS.MESSAGE, messageReceivedHandler);
};
}, [messageReceivedHandler, connector, isConnectorConnected]);
useDeepCompareEffect(() => {
isConnectorConnected && connector.subscribe(subscribedTopics, subscriptionOptions);
return () => {
subscribedTopics && connector?.unsubscribe(subscribedTopics);
};
}, [connector, isConnectorConnected, subscribedTopics, subscriptionOptions]);
return { isConnected: isConnectorConnected, isReconnecting: isConnectorReconnecting, connectionStatus, subscribedTopics };
现在错误轨迹是这样的:
Uncaught Error: Should have a queue. This is likely a bug in React. Please file an issue.
at updateReducer (react-dom.development.js:15255:15)
at updateState (react-dom.development.js:15671:12)
at Object.useState (react-dom.development.js:16472:18)
at useState (react.development.js:1533:23)
at customizedHook (customizedHook.js:28:38)
at componentThatConsumeHook (componentThatConsumeHook.js:67:99)
at renderWithHooks (react-dom.development.js:15015:20)
at updateFunctionComponent (react-dom.development.js:17386:22)
at beginWork (react-dom.development.js:19093:18)
at HTMLUnknownElement.callCallback (react-dom.development.js:3942:16)
并且浏览器中的开发控制台出现此警告:
Warning: React has detected a change in the order of Hooks called by myComponent. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
Previous render Next render
------------------------------------------------------
1. useRef useRef
2. useState useState
3. useEffect useEffect
4. useRef useState
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
customizedHook的第28行指向下面这一行:
const [someSubTopics] = useState([topics].flat());
这是我在组件中使用钩子的方式:
const result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);
我在这里挠头,因为我不知道为什么会这样,任何想法或建议将不胜感激!!!!
那是因为你在条件内调用 hook。
const result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);
与
基本相同let result = false
if (!!featureToggles.Flag){
result = customHook(arg1, callbackMethod);
}
来自 React 文档:
Don’t call Hooks inside loops, conditions, or nested functions.
您可以做的是将 featureToggles
传递到您的自定义挂钩中,然后在其中进行检查。
确保你的条件检查在你的挂钩底部,在每个挂钩调用下面。
// pass featureToggles here
export default function myCustomizedHook(featureToggles, topics, messagesReceivedFn, subscriptionOptions = {}) {
// your code here
useDeepCompareEffect(() => {
isConnectorConnected && connector.subscribe(subscribedTopics, subscriptionOptions);
return () => {
subscribedTopics && connector?.unsubscribe(subscribedTopics);
};
}, [connector, isConnectorConnected, subscribedTopics, subscriptionOptions]);
// make sure to do the check at the bottom, below every hook call
if (!!featureToggles.Flag) {
// handle this feature toggle
return null
}
return { isConnected: isConnectorConnected, isReconnecting: isConnectorReconnecting, connectionStatus, subscribedTopics };