Apollo加载在道具改变时总是假的[英] Apollo loading is always false on props change

本文是小编为大家收集整理的关于Apollo加载在道具改变时总是假的的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我是阿波罗的新手.我面临的问题是在初始(挂载/渲染)网络调用时进行,而在道具更改时却没有.

以下是我的应用程序的简化结构.

<Component (has filters in state)>
  <QueryComponent filters = {...filters} (passed to query)>

    <Table onChange/>

  </QueryComponent>
<Component/>
QueryComponent Code

export const QueryComponent = ({ callback, filter }) => {

  // Data transformation from filter to vars(expected by Query)

  return (
    <Query
      handleLoading
      query={query}
      returnPartialData
      variables={vars}
      fetchPolicy="network-only"
      callback={callback}
      getData={function}
      entityType="xx"
    />
  );
};

Query returns ApolloQuery

<ApolloQuery
    returnPartialData={returnPartialData}
    partialRefetch={partialRefetch}
    {...rest}
  >
    {
      ({
        data,
        loading,
      }) => {
        if (loading) {
          return handleLoading
            ? (
              <Loading />
            )
            : callback({
              loading,
            });
        }

        const queryData = data && getData(data);
        const hasValidData = !!queryData && !!Object
          .values(queryData)
          .filter((val) => !!val)
          .length;

        if (!hasValidData) {
          return passThruMissingData
            ? callback({
              loading,
              ...queryData,
            })
            : (
              <EntityNotFound
                type={entityType}
              />
            );
        }

        let strippedData = { ...queryData };
        const isValueAnArray = Object.values(strippedData)[0] instanceof Array;

        if (isValueAnArray) {
          strippedData = transform(
            strippedData,
            (result, value, key) => {
              value.forEach(deepStripInvalid);

              // eslint-disable-next-line no-param-reassign
              result[key] = value;
            },
          );
        } else {
          deepStripInvalid(strippedData);
        }

        return callback({
          ...strippedData,
        });
      }
    }
  </ApolloQuery>

and QueryComponent 有一个 Wrapper,它具有 Query as ApolloQuery 形式的 react-apollo 并且当 loading 为 true 时返回 loader.

在 <Table/> 组件中,我有更新组件中过滤器的处理程序,该过滤器向下流入 <QueryComponent />

在初始渲染时,过滤器被向下传递,我可以看到网络调用已经进行并且加载状态一秒钟为真,然后变为假.当我与表交互时调用 onChange 更新过滤器并将它们传递给查询,但加载状态返回 false 并且没有网络调用.

我也试过设置fetchPolicy="network-only"和fetchPolicy="no-cache",还是没有网络调用.

注意:目前后端没有数据,所以初始查询返回一个空数组.

我期望的行为:当过滤器被改变时,查询被再次调用并且应该有一个网络调用.

注意 2:如果我强制卸载并重新安装 <QueryComponent>,则会发出网络请求,但我更愿意使用 Apollo 的加载状态来处理.

react-apollo:"版本":"2.5.8"

阿波罗:"版本":"2.21.0"

已编辑以包含更多详细信息.

推荐答案

万一有人最终提出这个问题.深入研究这个问题,我发现 react-apollo 中的 Query 忽略了这里详细讨论的 fetchPolicy: network-only or no-cache https://github.com/apollographql/react-apollo/issues/556.由于遇到此问题的人和没有遇到此问题的人不一致,因此已关闭.

我们解决这个问题的方法是返回 refetch 和数据,并且在触发器上它没有再次发送网络调用,我们调用了 refetch 并且它再次强制发送调用.

本文地址:https://www.itbaoku.cn/post/1938104.html

问题描述

I am new to Apollo. Issue i am facing is that On initial (Mount/Render) network call is made and on prop change it isn't.

Following is simplified structure of my application.

<Component (has filters in state)>
  <QueryComponent filters = {...filters} (passed to query)>

    <Table onChange/>

  </QueryComponent>
<Component/>
QueryComponent Code

export const QueryComponent = ({ callback, filter }) => {

  // Data transformation from filter to vars(expected by Query)

  return (
    <Query
      handleLoading
      query={query}
      returnPartialData
      variables={vars}
      fetchPolicy="network-only"
      callback={callback}
      getData={function}
      entityType="xx"
    />
  );
};

Query returns ApolloQuery

<ApolloQuery
    returnPartialData={returnPartialData}
    partialRefetch={partialRefetch}
    {...rest}
  >
    {
      ({
        data,
        loading,
      }) => {
        if (loading) {
          return handleLoading
            ? (
              <Loading />
            )
            : callback({
              loading,
            });
        }

        const queryData = data && getData(data);
        const hasValidData = !!queryData && !!Object
          .values(queryData)
          .filter((val) => !!val)
          .length;

        if (!hasValidData) {
          return passThruMissingData
            ? callback({
              loading,
              ...queryData,
            })
            : (
              <EntityNotFound
                type={entityType}
              />
            );
        }

        let strippedData = { ...queryData };
        const isValueAnArray = Object.values(strippedData)[0] instanceof Array;

        if (isValueAnArray) {
          strippedData = transform(
            strippedData,
            (result, value, key) => {
              value.forEach(deepStripInvalid);

              // eslint-disable-next-line no-param-reassign
              result[key] = value;
            },
          );
        } else {
          deepStripInvalid(strippedData);
        }

        return callback({
          ...strippedData,
        });
      }
    }
  </ApolloQuery>

and QueryComponent has a Wrapper that has Query as ApolloQuery form react-apollo and it returns loader when loading is true.

In <Table/> component I have handler that updates the filters in Component which flows down into <QueryComponent />

On initial render Filters are passed down and i can see that network call has been made and loading state was true for a second and then change to false. When I interact with table onChange is called which updates the filters and they are passed to Query, but loading state return false and there is no network call.

I have tried to set fetchPolicy="network-only" and to fetchPolicy="no-cache" as well and there is still no network call.

Note: Currently there is no data on backend so initial query returns an empty array.

Behaviour I am expecting: When filters are changed query is called again and there should be a network call.

Note2: If I forcefully unmount and remount the <QueryComponent> then network request is made, but i would prefer to use Apollo's loading state to handle that.

react-apollo: "version": "2.5.8"

apollo: "version": "2.21.0"

Edited to include more details.

推荐答案

In case someone ends up coming to this question. Digging further into the problem I found that Query from react-apollo was ignoring fetchPolicy: network-only or no-cache discussed here in length https://github.com/apollographql/react-apollo/issues/556 . This was closed due to inconsistency of people having this issue and some who didn't.

The way we solved it is by returning refetch with the data and on the trigger it wasn't sending a network call again we called refetch and it forcefully send the call again.

相关标签/搜索