在React类组件中调用Apollo Client Hook报错求助
解决React类组件中使用Apollo Client Hook报错的问题
错误原因
你遇到的Invalid hook call错误,核心原因是React Hooks只能在函数组件的顶层作用域,或者其他自定义Hooks内部调用,类组件不支持Hooks语法。你在类组件的componentDidMount方法里调用了基于useQuery的自定义HookuseCompanyLogo,违反了Hooks的使用规则,因此触发了该错误。
解决方案
方案一:将类组件重构为函数组件(推荐)
React官方目前更推荐函数组件+Hook的写法,重构后代码更简洁,还能直接复用你已有的useCompanyLogo自定义Hook:
import React from 'react'; import { useCompanyLogo } from '../../queries/companyLogo'; const Logo = () => { const { error, loading, data } = useCompanyLogo(); // 处理加载和错误状态 if (loading) return <div>spinner</div>; if (error) return <div>error!</div>; const imageSource = data.companyLogo[0].image.urls[0]; return ( <div className="logo-area"> <a href="/"> <img src={`http://computer-313:5000${imageSource}`} alt="Businex-Logo" style={{width:"80px"}} /> </a> </div> ); }; export default Logo;
方案二:在类组件中使用Apollo Client的非Hook方式
如果需要保留类组件结构,可以选择以下两种实现方式:
方式1:使用Query渲染props组件
Apollo Client提供了Query组件,通过渲染props的方式在类组件中执行查询:
首先修改你的查询文件,导出COMPANY_LOGO查询:
import { useQuery, gql } from "@apollo/client"; export const COMPANY_LOGO = gql` query CompanyLogo { companyLogo { image { urls(first: 1) } } } `; export const useCompanyLogo = () => { const { error, data, loading } = useQuery(COMPANY_LOGO); console.log(error, data, loading); return { error, data, loading } }
然后修改类组件代码:
import React, { Component } from 'react'; import { Query } from '@apollo/client/react/components'; import { COMPANY_LOGO } from '../../queries/companyLogo'; class Logo extends Component { render() { return ( <Query query={COMPANY_LOGO}> {({ loading, error, data }) => { if (loading) return <div>spinner</div>; if (error) return <div>error!</div>; const imageSource = data.companyLogo[0].image.urls[0]; return ( <div className="logo-area"> <a href="/"> <img src={`http://computer-313:5000${imageSource}`} alt="Businex-Logo" style={{width:"80px"}} /> </a> </div> ); }} </Query> ); } } export default Logo;
方式2:通过Apollo Client实例直接调用query方法
使用withApollo高阶组件给类组件注入Apollo Client实例,然后在componentDidMount中手动执行查询:
import React, { Component } from 'react'; import { withApollo } from '@apollo/client/react/hoc'; import { COMPANY_LOGO } from '../../queries/companyLogo'; class Logo extends Component { state = { logo: "", loading: true, error: null }; componentDidMount() { // 通过props获取client实例,执行查询 this.props.client.query({ query: COMPANY_LOGO }) .then(({ data }) => { const imageSource = data.companyLogo[0].image.urls[0]; this.setState({ logo: imageSource, loading: false }); }) .catch((error) => { this.setState({ error, loading: false }); }); } render() { const { loading, error, logo } = this.state; if (loading) return <div>spinner</div>; if (error) return <div>error!</div>; return ( <div className="logo-area"> <a href="/"> <img src={`http://computer-313:5000${logo}`} alt="Businex-Logo" style={{width:"80px"}} /> </a> </div> ); } } // 用withApollo包裹组件,注入client实例 export default withApollo(Logo);
内容的提问来源于stack exchange,提问作者amin mohammadi
相关产品推荐
相关产品推荐

