【问题标题】:How to use Apollo useMutation in custom React hook如何在自定义 React 钩子中使用 Apollo useMutation
【发布时间】:2026-01-03 07:55:02
【问题描述】:

我仍然无法将头绕在 Hooks 上。我经常遇到问题,它抱怨我正在做Invalid hook call
这一次,是尝试在自定义钩子中使用来自 Apollo 的 useMutation 钩子。
如果有人能告诉我我做错了什么,我将不胜感激。

组件(我在其中调用自定义挂钩)

export default function MyComponent() {

    const { loading, error, data } = useQuery( GET_ORDERS );

    const setOrdersInMetafields = ( orders: Array<OrderModel> ) => {
        metafieldResp = useSetMetafields( { customerId, value: orders, field: 'duplicateOrders' } );
    }

    @useEffect( () => {
        setOrdersInMetafields( orders );
    }, [ orders ] );
}

自定义钩子

export const useSetMetafields( { customerId, value, field }, { customerId: string, value: any, field: string } ) => {
    [ updateMetafield, { loading, error, data } ] = useMutation( SET_METAFIELD_ON_CUSTOMER );

    useEffect( () => {
        onUpdateMetafield();
    }, [] );

    const onUpdateMetafield = () => {
        updateMetafield( {
            variables: {
                input: {
                    id: customerId,
                    metafields: [
                        {
                            namespace: 'app-name',
                            key: field,
                            value: JSON.stringify( value ),
                            type: 'string'
                        }
                    ]
                }
            }
        } );
    }
}

产生的错误:

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app

【问题讨论】:

  • 你的useEffect属于哪个组件?组件代码是否正确粘贴?如果这是 setOrdersInMetafields 组件的唯一内容,则可能违反了这条规则:Only Call Hooks from React Functions, not regular javascript functionsuseSetMetafields 钩子在常规 JS 函数 setOrdersInMetafields 中被调用。
  • 我已经更新了组件的代码示例。所以我从 React 组件调用自定义钩子。这构成了“反应功能”对吧?这段代码与我之前所做的不同。唯一的区别是我已将 useMutation 移至自定义挂钩,以使我的代码更加干燥。我想在其他组件中重用它。
  • 感谢您的更新。 Always use Hooks at the top level of your React function。你应该打电话给useSetMetafields,就在useQuery旁边。为了使您的代码正常工作,您需要更改自定义挂钩的方面。我将在答案部分分享一个建议。

标签: reactjs react-hooks next.js apollo-client react-custom-hooks


【解决方案1】:

Always use Hooks at the top level of your React function。你应该打电话给useSetMetafields,就在useQuery旁边。要使您的代码正常工作,您需要更改自定义挂钩的方面。我的建议,以及您提供的代码量:


export default function MyComponent() {
    const { loading, error, data } = useQuery( GET_ORDERS );
    { doUpdateMetaField } = useSetMetafields();

  const setOrdersInMetafields = ( orders: Array<OrderModel> ) => {
// Make doUpdateMetaField function return something if you need and collect it here
       doUpdateMetaField( { customerId, value: orders, field: 'duplicateOrders' } );
    }
    useEffect( () => {
        setOrdersInMetafields( orders );
    }, [ orders ] );
}

export const useSetMetafields = () => {
    [ updateMetafield, { loading, error, data } ] = useMutation( SET_METAFIELD_ON_CUSTOMER );

    const doUpdateMetaField = ({ customerId, value, field }, { customerId: string, value: any, field: string } ) => {
        updateMetafield( {
            variables: {
                input: {
                    id: customerId,
                    metafields: [
                        {
                            namespace: 'app-name',
                            key: field,
                            value: JSON.stringify( value ),
                            type: 'string'
                        }
                    ]
                }
            }
        } );
    }

return {
   doUpdateMetaField
}
}


【讨论】:

  • 啊,我明白我做错了什么。我不应该像那样直接调用自定义钩子。这有很大帮助。谢谢!
最近更新 更多