Apollo:组件重新渲染之间的加载状态

Posted

技术标签:

【中文标题】Apollo:组件重新渲染之间的加载状态【英文标题】:Apollo: Loading state between re-renders of the component 【发布时间】:2019-11-03 03:10:05 【问题描述】:

我有以下组件。

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

import Table from 'components/Table';
import  useQueryParams  from 'customHooks';
import  LOCATIONS  from 'graphql/queries';

const useLocations = ( filters, max, sorting ) => 
    const variables =  max, filters, sorting ;
    return useQuery(LOCATIONS,  variables, fetchPolicy: 'network-only' );
;

const Search = ( filters, sorting ) => 
    // Gets the value for the parameter "max" from the URL, with default 100
    const  max, updateURLParam  = useQueryParams( max: 100 );

    const  data, error, loading  = useLocations( filters, sorting, max );

    if (loading && !data.myData) return <div>Loading</div>;

    if (error) return <div>Error</div>;

    // Update the URL parameter "max"
    // Example
    // Before: https://localhost:3000/table?max=100
    // After: https://localhost:3000/table?max=200
    const handleReachBottom = () => updateURLParam( max: max + 100 );

    return <Table.Locations data=data onReachBottom=handleReachBottom />;
;

export default Search;

我所期待的行为如下:

    显示“正在加载” 显示包含数据的表格 滚动到表格底部 在获取新数据时,表格仍在显示中 获取数据后,更新表

在我使用来自 apollo 的 Query component 之前,它的工作原理完全一样。但是当我切换到react-apollo-hooks 包时,行为变成了这个:

    显示“正在加载” 显示包含数据的表格 滚动到表格底部 显示“正在加载” 获取数据后,更新表

为什么会这样?

更新

这就是我之前使用它的方式:

import React from 'react';
import  Query  from 'react-apollo';


import Table from 'components/Table';
import useQueryParams from 'customHooks/useQueryParams';

const Locations = ( filters, max, sorting, children ) => 
    const variables =  max, sorting ;

    return (
        <Query ... variables  query=LOCATIONS fetchPolicy='network-only'>
            children
        </Query>
    );
;


const Search = ( filters, sorting ) => 
    const  max, updateURLParam  = useQueryParams( max: 100 );

    return (
        <MyClient.Locations ... filters, sorting, max >
            ( data, loading, error ) => 
                if (loading && !data.myData) return <div>Loading</div>;

                if (error) return <div>Error</div>;

                const handleReachBottom = () => updateURLParam( max: max + 100 );


                return (
                    <Table.Locations
                        data=data
                        onReachBottom=handleReachBottom
                    />
                );
            
        </MyClient.Locations>
    );
;

export default Search;

【问题讨论】:

您之前是如何使用查询组件的?因为这里 loading 会在重新获取时设置为 true 并且if (loading) return &lt;div&gt;Loading&lt;/div&gt;; 会返回正在加载的 div 我用该信息更新了问题 不确定这是否可行,但您可以尝试 notifyOnNetworkStatusChange: false 作为 useQuery 挂钩的第二个参数。 不,这没有解决任何问题 我使用if (loading &amp;&amp; !data.myData)更新了问题,这很有意义,但问题仍然存在 【参考方案1】:

我之前在使用react-apollo-hooks 时遇到过这个问题,我觉得重新获取、变量和 fetchPolicy 的行为与标准 Apollo 略有不同。我从来没有深究过。

我解决它的方法是不要使用 loading 属性,而是使用数据本身的存在来决定要做什么。这种方法在重新获取时有效

const [data, setData] = useState(null)

const res = useLocations( filters, sorting, max );

useEffect(() => 
  if (Object.keys(res.data || ).length > 0) 
    setData(res.data)
  
, [res.data])

if (!data) return <div>Loading</div>

【讨论】:

如果我使用if (loading &amp;&amp; !data.myData) return &lt;div&gt;Loading&lt;/div&gt;;,我仍然会遇到同样的问题。似乎data 每次重新获取时都会重置为 是的数据被重置为 ...所以我上面的解决方案是使用useState钩子在本地缓存它。仅当数据 isnt . 时才更新该本地缓存 我最终制作了一个自定义钩子来处理它,给你gist.github.com/jedrichards/c02af3496f4e304b720a9624db647dfb 哇...哦,太好了

以上是关于Apollo:组件重新渲染之间的加载状态的主要内容,如果未能解决你的问题,请参考以下文章

React、Apollo 2、GraphQL、身份验证。登录后如何重新渲染组件

Apollo graphql 连接的 React 组件没有重新渲染

Apollo fetchMore 更新的 props 不重新渲染组件

在 Apollo-client 中,writeQuery 会更新缓存,但 UI 组件不会重新渲染

Blazor 服务器端 SPA:重新加载组件后的组件状态

如何避免在反应功能组件中对“静态组件”进行不必要的重新渲染?