I've been working with Javascript for a couple of years now, and with my current knowledge of the event loop I'm struggling to understand why this testing recipe from the React docs work. Would someone be able to break down exactly what happens in each step there? To me, it seems magical that this works in the test:
await act(async () => {
render(<User id="123" />, container);
});
// expect something
The component looks like this (copying in case that link gets deprecated):
function User(props) {
const [user, setUser] = useState(null);
async function fetchUserData(id) {
const response = await fetch("/" + id);
setUser(await response.json());
}
useEffect(() => {
fetchUserData(props.id);
}, [props.id]);
if (!user) {
return "loading...";
}
return (
<details>
<summary>{user.name}</summary>
<strong>{user.age}</strong> years old
<br />
lives in {user.address}
</details>
);
}
There's no implicit or explicit return happening on the render, so how does act know to await the async stuff happening in the component (fetching etc)?
To me, this would make more sense:
await act(async () => render(<User id="123" />, container));
or (which is the same thing):
await act(async () => {
return render(<User id="123" />, container);
});
or even:
await act(render(<User id="123" />, container));
But that doesn't seem to be how people use it, or how it was intended to be used, so I'm a bit lost. I've seen the same examples with enzymes mount.
I don't want to create a fragile test, so I really want to understand this.
Does it have something to do with the callback being async i.e. does that append something to the event loop last, making it so that the await waits for everything inside render to happen before resolving?
I'm drawing a blank here and am struggling in the react doc jungle, because everyone seems to use this pattern, but no one really explains why or how it works.
Thanks for the help in advance!