React-Apollo - 查询 - renderProp:反应警告:无法对未安装的组件执行反应状态更新

Posted

技术标签:

【中文标题】React-Apollo - 查询 - renderProp:反应警告:无法对未安装的组件执行反应状态更新【英文标题】:React-Apollo - Query - renderProp: React warning: Can't perform a React state update on an unmounted component 【发布时间】:2020-03-20 02:37:14 【问题描述】:

我正在使用“react-apollo”中的“Query”,我的应用程序返回了这个错误。我想我理解了这个问题:我的应用程序正在尝试重新渲染一个已卸载的组件。我不确定如何解决该错误。我一直在阅读 Apollo 和 React 的官方文档,但我仍然不知道如何修复。

好像其他用户和我有同样的问题:https://github.com/apollographql/react-apollo/issues/3635

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in Query (at GetListOfUsers.js:19)
    in GetListOfUsers (at UserAdministration.js:11)
    in UserAdministration (at App.js:54)

这是我的代码:

// GetListOfUsers.js

import React from 'react'

import  ListOfUsers  from '../components/ListOfUsers'
import  Spinner  from '../components/Spinner'
import  ErrorAlert  from '../components/ErrorAlert'

import  Query  from 'react-apollo'

import  LIST_ALL_USERS  from '../gql/queries/users';

const renderProp = (  loading, error, data  ) => 
    if (loading) return <Spinner key='loading' />
    if (error) return <ErrorAlert errorMessage=error.message />

    return <ListOfUsers users=data.listAllUsers || [] />


export const GetListOfUsers = () => (
    <Query query=LIST_ALL_USERS fetchPolicy="cache-and-network">
        
            renderProp
        
    </Query>
)

// ListOfUsers.js

import React from 'react'
import PropTypes from 'prop-types'

import  parseUnixTimestamp  from '../../utils/utils'

export const ListOfUsers = (  users = []  ) => 
    return (
        <section className="table-responsive">
            <table className="table text-light">
                <thead>
                    <tr>
                        <th scope="col">Email</th>
                        <th scope="col">Is administrator ?</th>
                        <th scope="col">Is active ?</th>
                        <th scope="col">Registration date</th>
                        <th scope="col">Last login</th>
                    </tr>
                </thead>
                <tbody>
                    
                        users.map(user => 
                            return (
                                <tr key=user.uuid>
                                    <td>user.email</td>
                                    <td>(user.isAdmin) ? 'yes': 'no'</td>
                                    <td>(user.isActive) ? 'yes': 'no'</td>
                                    <td>parseUnixTimestamp(user.registrationDate)</td>
                                    <td>parseUnixTimestamp(user.lastLogin)</td>
                                </tr>
                            )
                        )
                    
                </tbody>
            </table>
        </section>
    )



ListOfUsers.propTypes = 
    users: PropTypes.arrayOf(
        PropTypes.shape(
            email: PropTypes.string.isRequired,
            uuid: PropTypes.string.isRequired,
            isAdmin: PropTypes.bool.isRequired,
            isActive: PropTypes.bool.isRequired,
            registrationDate: PropTypes.string.isRequired,
            lastLogin: PropTypes.string.isRequired
        )
    )


“GetListOfUsers”在这里被调用:

// UserAdministration.js

import React,  Fragment  from 'react'

import  PageTitle  from '../components/PageTitle'

import  GetListOfUsers  from '../containers/GetListOfUsers'

const UserAdministration = () => 
    return (
        <Fragment>
            <PageTitle text='User administration panel' />
            <GetListOfUsers />
        </Fragment>
    )


UserAdministration.displayName = 'UserAdministration'

export default UserAdministration

我尝试修改文件“GetListOfUsers”以使用“useQuery”并遇到同样的问题。我的代码是这样的:

// GetListOfUsers.js

import React from 'react'
import  useQuery  from 'react-apollo'

import  Spinner  from '../components/Spinner'
import  ErrorAlert  from '../components/ErrorAlert'
import  ListOfUsers  from '../components/ListOfUsers'

import  LIST_ALL_USERS  from '../gql/queries/users';

export const GetListOfUsers = () => 
    const  loading, error, data  = useQuery(LIST_ALL_USERS);

    if (loading) return <Spinner />
    if (error) return <ErrorAlert errorMessage=error.message />

    return <ListOfUsers users=data.listAllUsers || [] />

【问题讨论】:

乍一看似乎你需要renderProp()而不是renderProp,或者写,因为它是一个react组件函数。 看来在使用react组件函数的时候还是用Apollo-hooks比较好。我个人使用withApollo直接在类组件中访问客户端,或者在功能组件中使用useApolloClient钩子。 但是在 apollo-hooks 中有 useQuery 和 useLazyQuery ,....我对您的主要问题的个人看法是您在功能组件中使用查询组件,将其更改为 useQuery 挂钩并查看结果。 你能给我举个例子吗?我不是 React 或 Apollo 方面的专家 apollographql.com/docs/react/api/react-hooks 【参考方案1】:

我遇到了同样的问题,并为我的案例找到了两种解决方案:

    删除fetchPolicy: 'cache-and-network'(可能不是你想要的)

    将 Apollo 升级到新的 v3.0(撰写此答案时仍处于测试阶段)

这两个选项都修复了对我的警告。

【讨论】:

不,错误仍然出现在严格模式下,我从过去 4 天开始一​​直在尝试修复,现在我知道是什么导致了问题,这是因为严格模式github.com/apollographql/react-apollo/issues/3635

以上是关于React-Apollo - 查询 - renderProp:反应警告:无法对未安装的组件执行反应状态更新的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 react-apollo 查询的变量

React-Apollo:带变量的查询导致 UI 不再乐观

ReactJS/Javascript/Graphql/React-apollo:传递查询变量

如何使用 react-apollo 运行 graphQL 查询?

如何使用 react-apollo 使用相同的查询进行多个 graphql 查询?

react-apollo 网络错误:查询“Hello”的服务器响应丢失