【问题标题】:Relay - usePreloadedQuery hook is suspending rendering while mounting with enzyme中继 - usePreloadedQuery 挂钩在使用酶安装时暂停渲染
【发布时间】:2021-11-18 03:50:16
【问题描述】:

我在尝试对使用 usePreloadedQuery 的组件进行单元测试时收到以下错误:

Error: A React component suspended while rendering, but no fallback UI was specified.

Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.

我有一个接收查询引用的父组件,它使用usePreloadedQuery 来检索数据,如下所示:

type Props = {
   queryReference: PreloadedQuery<parentComponentQuery>,
};

export const ParentComponent = ({ queryReference }: Props) => {
  const { data } = usePreloadedQuery(
    graphql`
        query parentComponentQuery($someId: ID!) {
            something(someId: $someId) {
                    ...childComponentFragment
                }
            }
        }
    `,
    queryReference,
  );

  return (
      <div>
         <ChildComponent fragmentRef={data.childData} />
      </div>
   )
}

这里的queryReference 是通过调用loadQuery 创建的,它由一个内部钩子处理,它是react-resource-routeruseResource 的包装器,用于中继资源。


我正在尝试使用 Jest 和 Enzyme 以及以下代码来测试这个组件:

let queryReference;
const mockRelayPayload = () => {
  const environment = createMockEnvironment();
  environment.mock.queueOperationResolver((operation) =>
    MockPayloadGenerator.generate(operation, {
        Something: () => ({
            // ... data
        }),
    }),
  );
  environment.mock.queuePendingOperation(QUERY, {});

  act(() => {
     queryReference = loadQuery(environment, QUERY, {}); // fire mocked API call
  });

  return environment;
};

it('should render correctly', () => {
    const environment = mockRelayPayload();
    const wrapper = mount(
        <RelayEnvironmentProvider environment={environment}>
            {/*<Suspense fallback={<div>Loading... </div>}>*/}
               <ParentComponent  queryReference={queryReference}/>
            {/*</Suspense>*/}
        </RelayEnvironmentProvider>
    );
    
    expect(wrapper.find(Wrapper)).toExist();
});

根据文档Testing Relay Components

为了使usePreloadedQuery 挂钩不挂起,必须调用 这些功能:

  • queueOperationResolver(resolver)
  • queuePendingOperation(query, variables)
  • preloadQuery(mockEnvironment, query, variables) 具有相同的查询和传递的变量 到queuePendingOperationpreloadQuery 必须在之后调用 queuePendingOperation

我正在执行前两个步骤,但我无法从 react-relay 导入 preloadQuery,基于 github 源/flowtypes 看起来它已被弃用/删除。所以我改为使用loadQuery

act(() => {
     queryReference = loadQuery(environment, QUERY, {}); // fire mocked API call
});

但是会抛出前面提到的错误。

从注释代码中可以看出,我也尝试按照错误中的建议使用&lt;Suspense&gt;,不幸的是它从enzyme-adapter-react-16 抛出Error: Enzyme Internal Error: unknown node with tag 2

【问题讨论】:

    标签: reactjs jestjs enzyme relay react-relay


    【解决方案1】:

    折腾了几天终于找到问题所在了:

      environment.mock.queuePendingOperation(QUERY, {});
    
      act(() => {
         queryReference = loadQuery(environment, QUERY, {});
      });
    

    这应该是

    environment.mock.queuePendingOperation(QUERY, { someId: "value" });
    
    let queryReference;
    act(() => {
        queryReference = loadQuery(environment, QUERY, { someId: "value" }); 
    });
    

    似乎当您使用queueOperationResolver 时,只有当查询"signature" 与查询和变量 完全匹配时,它才会解析 > 你传递给queuePendingOperationloadQuery

    在我的例子中,我传递了一个空变量对象 {} 而不是 { someId: "value" } 所以解析器根本没有解析查询。

    不幸的是,这里抛出的错误消息不是很有用,而不是说查询永远不会解决它只是告诉你使用&lt;Suspense&gt;,这有点误导。

    【讨论】:

      猜你喜欢
      • 2017-10-20
      • 2019-05-27
      • 1970-01-01
      • 2020-07-12
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多