0

尝试对使用的组件进行单元测试时出现以下错误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-router的 包装器。useResource


我正在尝试使用 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();
});

根据文档测试中继组件

为了使usePreloadedQuery钩子不挂起,必须调用这些函数:

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

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

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

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

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

4

1 回答 1

0

经过几天的努力终于找到了问题,它就在这里:

  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,它只会在查询“签名”与您传递给 的查询和变量完全匹配时解决and 。queuePendingOperationloadQuery

在我的情况下,我传递了一个空变量对象{},而不是{ someId: "value" }因此解析器根本没有解析查询。

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

于 2021-11-18T04:50:07.923 回答