Update to allow components to render undefined #75
rickhanlonii
announced in
Announcement
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Overview
We’ve made update to allow rendering undefined instead throwing.
In this post I want to share a bit about the reasoning and why we’re changing this in React 18.
Background
Before this change, if a component rendered
undefined
, React would throw an error at runtime:The intent of this behavior was to help users catch a common issue of forgetting a return statement accidentally. This is an easy mistake when using early returns or multiple returns:
For use cases where this behavior was intentional, you could indicate that by returning
null
instead:Issues with throwing
There are a couple of issues with throwing at runtime when rendering undefined.
1. Linting is better for this use case
At runtime, you can’t tell the difference between forgetting to return and explicitly returning
undefined
, but this is something linting can check for because it operates on the code syntax as it’s written instead of how it’s executed.Linting is also able to give more specific messages for why you may have made an accident, such as “this function is missing a return statement” (consistent-return), or “this expression was unused” (no-unused-expressions). More specific messages with code frames pointing you to the source of the issue will help you find the issue quicker than a generic run time error.
2. Creating a correct type is hard
Another issue of not allowing undefined is that it’s difficult create a proper type for something React can render. For example, in the old behavior where we throw for
undefined
, let’s say you want to render thechildren
prop in component:How would you type
ComponentType
so that it can be used to typechildren
andFoo
? You can’t includeundefined
because it would error at runtime. But if you excludeundefined
, then everywhere you pass the children down to Foo, you would need to check if the children areundefined
:Not being able to create a general type of something React can render that you can use in place of any prop or component that is passed through your app has been a long standing issue in the ecosystem. By allowing
undefined
to be rendered, it becomes easy to create a type that’s the same across type systems.Why now?
When we first added this error in 2017, type systems and linting in the ecosystem were not as popular or robust as they are today, and there were a lot of runtime checks like
prop-types
being done to help developers find unsafe issues. Since then, the community has evolved and these tools have grown in popularity, so it’s a good time to re-visit this feature to replace it with something better.To give some insight into how the team started considering this change, it recently came up in discussions for future features such as Suspense and server components. For Suspense, we recently made an update to how we handle
null
orundefined
fallbacks, allowing undefined fallbacks to render. But if the fallback is undefined, why doesn't it error? There's an inconsistency there that we wanted to fix.For server components, it’s important to have a general type for things React can render because you may need to be able to accept children passed from server components. The current complexity of types will only become more complex as we add features, so it's important to fix this issue now.
Beta Was this translation helpful? Give feedback.
All reactions