使用 GraphQL 在 NextJS 中呈现比之前呈现更多的钩子

Rendered more hooks than during the previous render in NextJS using GraphQL

我将导航栏放在 _app.js 中,这样我就不需要在每个组件中都插入它。我的问题是,在我登录后它输出错误 Rendered more hooks than during the previous render. 并将其指向 useQuery(GETCARTDATA

请在此处检查我的代码

const App = ({ Component, pageProps }) => {
    const token = getToken()
    const [isPopUpShow, setPopUpShow] = useState(false)
    const [cartStateData, setCartStateData] = useState([])
    const [isCartOpen, setCartOpen] = useState(false)
    let cartDetailsData
    
    if (token) {
      // eslint-disable-next-line react-hooks/rules-of-hooks
      cartDetailsData = useLazyQuery(GETCARTDATA, {
        variables: {
          page: 1
        },
      })
      // eslint-disable-next-line react-hooks/rules-of-hooks
      useMemo(() => {
        const cartData = get(cartDetailsData.data, 'findCartDetails.orders') || []
        const cartItems = []
        if (cartData.length) {
          cartData.map(
            itm =>
              itm.lineItems.length &&
              itm.lineItems.map(item => cartItems.push(item))
          )
        }
        setCartStateData(cartItems)
      }, [cartDetailsData.data])
    }
  
    return (
      <>
        <div className="app-outer">
          {token ? (
            <ShowroomHeader
              isPopUpShow={isPopUpShow}
              setPopUpShow={setPopUpShow}
              cartStateData={cartStateData}
              cartDetailsData={cartDetailsData}
              token={token}
            />
          ) : (
            <Navbar />
          )}
        </div>
  
        <div className="main">
          <Component {...pageProps} />
        </div>

      </>
    )
  }
  
  export default withApollo(App)

, you're rendering your hooks conditionally while React expects the same number of hook calls on every render, thus breaking the rules of Hooks.

您需要删除 if 语句并将您的条件移到 useEffect 挂钩中,使用 useLazyQuery 的返回函数从那里执行查询。您还可以将 useMemo 代码移动到 onCompleted 回调,因为它取决于查询的结果。

const App = ({ Component, pageProps }) => {
    const token = getToken()
    const [isPopUpShow, setPopUpShow] = useState(false)
    const [cartStateData, setCartStateData] = useState([])
    const [isCartOpen, setCartOpen] = useState(false)

    const [getCardData, cartDetailsData] = useLazyQuery(GETCARTDATA, {
        onCompleted: (data) => {
            const cartData = get(data, 'findCartDetails.orders') || []
            const cartItems = []
            if (cartData.length) {
                cartData.map(
                    itm =>
                        itm.lineItems.length &&
                        itm.lineItems.map(item => cartItems.push(item))
                )
            }
            setCartStateData(cartItems)
        }
    })

    useEffect(() => {
        if (token) {
            getCardData({ variables: { page: 1 } })
        }
    }, [token])
  
    return (
        // Your JSX here
    )
}