Edw*_*Sun 1 javascript reactjs react-hooks react-state
我有一个反应组件,需要从组件内使用自定义的反应挂钩。
但是,只有在启用功能切换时才应调用此挂钩。我知道这是一种反模式,因为它违反了这里的钩子规则: 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
)
Run Code Online (Sandbox Code Playgroud)
对于定制的钩子:
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 };
Run Code Online (Sandbox Code Playgroud)
现在错误跟踪是这样的:
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)
Run Code Online (Sandbox Code Playgroud)
并且浏览器中的开发控制台有此警告:
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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
customizedHook 的第 28 行指向下面这一行:
const [someSubTopics] = useState([topics].flat());
Run Code Online (Sandbox Code Playgroud)
这就是我在组件中使用钩子的方式:
const result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);
Run Code Online (Sandbox Code Playgroud)
我在这里摸不着头脑,因为我不知道为什么会发生这种情况,任何想法或建议将不胜感激!
那是因为你在条件内调用 hook 。
\nconst result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);\nRun Code Online (Sandbox Code Playgroud)\n基本上是一样的
\nlet result = false\nif (!!featureToggles.Flag){\n result = customHook(arg1, callbackMethod);\n}\nRun Code Online (Sandbox Code Playgroud)\n来自React文档:
\n\n\n不要\xe2\x80\x99t 在循环、条件或嵌套函数内调用 Hook。
\n
您可以做的就是传递featureToggles到您的自定义挂钩并在其中进行检查。
确保您的条件检查位于钩子的底部,位于每个钩子调用的下方。
\n// pass featureToggles here\nexport default function myCustomizedHook(featureToggles, topics, messagesReceivedFn, subscriptionOptions = {}) {\n // your code here\n\n useDeepCompareEffect(() => {\n isConnectorConnected && connector.subscribe(subscribedTopics, subscriptionOptions);\n\n return () => {\n subscribedTopics && connector?.unsubscribe(subscribedTopics);\n };\n }, [connector, isConnectorConnected, subscribedTopics, subscriptionOptions]);\n\n // make sure to do the check at the bottom, below every hook call\n if (!!featureToggles.Flag) {\n // handle this feature toggle\n return null\n }\n\n return { isConnected: isConnectorConnected, isReconnecting: isConnectorReconnecting, connectionStatus, subscribedTopics };\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
3781 次 |
| 最近记录: |