javascript - React custom hook spit Error " Error: Should have a queue. This is likely a bug in React. Please file an i

I have react ponent which needs to consume a customized react hook from within the ponent.However, thi

I have react ponent which needs to consume a customized react hook from within the ponent.

However, this hook should only be called when a feature toggle is enabled. I understand this is sort of anti-pattern as it is against the rule of hooks here: .html

So my ponent file is roughly in this structure:

    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
      )

For the customized hook:

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 };

Now the error trace is like this:

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 ponentThatConsumeHook (ponentThatConsumeHook.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)

and there is this warning from dev console in the browser:

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: 

   Previous render            Next render
   ------------------------------------------------------
1. useRef                     useRef
2. useState                   useState
3. useEffect                  useEffect
4. useRef                     useState
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

line 28 of customizedHook is point to this line below:

const [someSubTopics] = useState([topics].flat());

This is how I consume the hook in the ponent:

const result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);

I am scratching my head here as I have no clue why this is happening, any thought or advice would be greatly appreciated !!!!

I have react ponent which needs to consume a customized react hook from within the ponent.

However, this hook should only be called when a feature toggle is enabled. I understand this is sort of anti-pattern as it is against the rule of hooks here: https://reactjs/docs/hooks-rules.html

So my ponent file is roughly in this structure:

    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
      )

For the customized hook:

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 };

Now the error trace is like this:

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 ponentThatConsumeHook (ponentThatConsumeHook.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)

and there is this warning from dev console in the browser:

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/link/rules-of-hooks

   Previous render            Next render
   ------------------------------------------------------
1. useRef                     useRef
2. useState                   useState
3. useEffect                  useEffect
4. useRef                     useState
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

line 28 of customizedHook is point to this line below:

const [someSubTopics] = useState([topics].flat());

This is how I consume the hook in the ponent:

const result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);

I am scratching my head here as I have no clue why this is happening, any thought or advice would be greatly appreciated !!!!

Share Improve this question edited Feb 22, 2022 at 3:19 Edward Sun asked Feb 22, 2022 at 3:09 Edward SunEdward Sun 531 silver badge6 bronze badges 1
  • Conditionally calling hooks is not “sort of an anti-pattern” as you describe it. It results (as you’ve discovered) in plain brokenness. Hooks 100% rely on the fact that they are never called conditionally. Mess around and find out, to paraphrase. – Adam Jenkins Commented Feb 22, 2022 at 3:46
Add a ment  | 

1 Answer 1

Reset to default 7

That's because you're calling hook inside a condition.

const result = (!!featureToggles.Flag) && customHook(arg1, callbackMethod);

is basically the same as

let result = false
if (!!featureToggles.Flag){
  result = customHook(arg1, callbackMethod);
}

From React document:

Don’t call Hooks inside loops, conditions, or nested functions.

What you could do is to pass featureToggles into your custom hook and do the check inside that instead.

Make sure your condition check is at the bottom of your hook, below every hook call.

// 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 };

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742339244a4425283.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信