I’m used to using htm
, a JSX-like syntax via tagged templates, which allows me to write anonymous components like this:
let loc;
render(
html`
<div>
<${() => {
loc = useLocation();
}} />
</div>
`,
scratch
);
// test value of `loc`
However, I can’t figure out what the equivalent JSX syntax is. I use this a lot in tests, cuts down on the number of irrelevant components I need to write just to extract a hook value out of a test render.
2
Answers
JSX doesn’t have that feature — presumably because it’s a bad idea outside of test code (you’d get a new component-type on every render, which means that every render has to completely unmount the old component and create a new one) — but you can use
createElement
directly:// How to define an inline component with JSX?
I will answer your question in two parts:
1. How to render an "anonymous" component
In React/JSX pretty much any function that returns JSX can be rendered as a component (note that the function name will usually start with a capital letter).
And since you can write functions pretty much anywhere, you can define a functional component directly inside each test, much like you have in your example.
So the direct translation of your example into JSX would be:
The use of the
loc
variable is probably not the recommended way of testing hooks, but it works…You could then split out the rendering part to its own function if you wanted truly anonymous components for your test:
2. How to test hooks
I would recommend looking at a dedicated library like
@testing-library/react
(formerlyreact-testing-library
).This has a bunch of helper functions to cut down on boilerplate code.
Specifically, the renderHook() function would be worth looking at – it allows you to run hooks without having to render them inside a component.
Here’s an example of how you could convert your example to use
renderHook()
instead:Final note – the
doRender()
example above is a really dumb version of what the @testing-library/react render() function lets you do, so I would recommend using that.