[英]Relay - usePreloadedQuery hook is suspending rendering while mounting with enzyme
I get the below error while trying to unit test a component which uses usePreloadedQuery
:尝试对使用
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.
I have a parent component that receives a query reference, and it is using usePreloadedQuery
to retrieve the data as shown below:我有一个接收查询引用的父组件,它使用
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>
)
}
The queryReference
here is created via call to loadQuery
, which is handled by an internal hook, that is a wrapper around react-resource-router
's useResource
for relay resources.这里的
queryReference
是通过调用loadQuery
创建的,它由一个内部钩子处理,它是react-resource-router
用于中继资源的useResource
的包装器。
I'm trying to test this component using Jest and Enzyme with the following code:我正在尝试使用 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();
});
According to the docs Testing Relay Components :根据文档测试中继组件:
in order for the
usePreloadedQuery
hook to not suspend, one must call these functions:为了使
usePreloadedQuery
挂钩不挂起,必须调用这些函数:
queueOperationResolver(resolver)
queuePendingOperation(query, variables)
preloadQuery(mockEnvironment, query, variables)
with the same query and variables that were passed toqueuePendingOperation
.preloadQuery(mockEnvironment, query, variables)
与传递给queuePendingOperation
的相同查询和变量。preloadQuery
must be called afterqueuePendingOperation
preloadQuery
必须在queuePendingOperation
之后调用
I'm doing the first two steps, but I'm not able to import preloadQuery
from react-relay
, based on github source/flowtypes looks like it is deprecated/removed.我正在执行前两个步骤,但我无法从
react-relay
导入preloadQuery
,基于 github source/flowtypes 看起来它已被弃用/删除。 So instead I'm using loadQuery
as in所以我使用的是
loadQuery
act(() => {
queryReference = loadQuery(environment, QUERY, {}); // fire mocked API call
});
But it throws the error mentioned earlier.但它会抛出前面提到的错误。
As you can tell from the commented code, I've also tried using <Suspense>
as suggested in the error, unfortunately it throws Error: Enzyme Internal Error: unknown node with tag 2
from enzyme-adapter-react-16
正如您从注释代码中可以看出的那样,我也尝试按照错误中的建议使用
<Suspense>
,不幸的是它抛出Error: Enzyme Internal Error: unknown node with tag 2
来自enzyme-adapter-react-16
标签为2的未知节点
Finally found the issue after days of struggle, it was here:经过几天的努力终于找到了问题,它就在这里:
environment.mock.queuePendingOperation(QUERY, {});
act(() => {
queryReference = loadQuery(environment, QUERY, {});
});
This should be这应该是
environment.mock.queuePendingOperation(QUERY, { someId: "value" });
let queryReference;
act(() => {
queryReference = loadQuery(environment, QUERY, { someId: "value" });
});
It seems like when you use queueOperationResolver
, it'll only resolve if the query "signature" exactly matches the query and variables you pass to queuePendingOperation
and loadQuery
.似乎当您使用
queueOperationResolver
时,只有当查询“签名”与您传递给queuePendingOperation
和loadQuery
的查询和变量完全匹配时,它才会解析。
In my case I was passing an empty variables object {}
instead of { someId: "value" }
so the resolver wasn't resolving the query at all.在我的情况下,我传递了一个空变量 object
{}
而不是{ someId: "value" }
所以解析器根本没有解析查询。
Unfortunately the error message thrown here isn't very useful, instead of saying the query is never resolved it just tells you to use <Suspense>
which is a bit misleading.不幸的是,这里抛出的错误消息不是很有用,而不是说查询永远不会解决它只是告诉你使用
<Suspense>
这有点误导。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.