好吧,这听起来可能很复杂,但如果您阅读以下示例,就会很容易。这样做的主要目的是将逻辑与实际渲染代码分开。使组件更小,(理论上)更易于测试。
class NameProvider {
public getName(): Promise<string> {
return Promise.resolve("Cool name");
}
}
interface RenderProps {
name: string;
onGetNamePress(): void;
}
interface LogicProps {
nameProvider: NameProvider;
render: React.ComponentType<RenderProps>
}
function Render({name, onGetNamePress}: RenderProps): React.ReactElement {
return <>
<p>{name}</p>
<button title="Get name!" onClick={onGetNamePress} />
</>
}
function Logic({nameProvider, render: Render}: LogicProps): React.ReactElement {
const [name, setName] = React.useState<string>();
return <Render
name={name}
onGetNamePress={fetch}
/>
async function fetch() {
setName(await nameProvider.getName());
}
}
测试渲染组件相当容易,但我如何测试传递给渲染组件的道具是否正确?尤其是在状态改变之后。
考虑以下事项:
it('fetches the name after the button was pressed', () => {
const mnp = new MockNameProvider();
render(<Logic
nameProvider={mnp}
render={({name, onGetNamePress}) => {
act(async () => {
await onGetNamePress();
expect(name).toBe(mockName);
})
}}
/>)
})
这将导致无限循环,因为状态不断变化并获取名称。我也无法想象如何获得新道具。根据我的理解,此当前代码将测试旧代码。所以我的问题是,我如何测试 props 是否正确传递(也在更新之后)。
(重要)注意事项:
React
前缀,vscode 在未保存的文件中更喜欢它。