React Owner Components
Owners vs Parents & Why It Matters for Server Components and Client Components.
See Our Public Workshops:
In React, the term "owner" can be used to describe a component in the hierarchy, similar to using the term "parent". It's somewhat of a lost term that I almost never see newer React developers use anymore. The term was used more heavily in the earlier days of React and is still useful today, especially when it comes to understanding client components vs server components (RSC).
Let's jump strait to an example which describes it best:
function UserProfile() {const [user, setUser] = useState({})return (<div><span></span></div>)}
In this example, we would say div
is a parent and span
is the child right? JSX uses the same parent-child terminology that is used in HTML or XML. Now let's rewrite with components:
function UserProfile() {const [user, setUser] = useState({})return (<ProfileLayout><Avatar /></ProfileLayout>)}
We didn't change much about the hierarchy. ProfileLayout
is the parent and Avatar
is the child. The "owner" component is UserProfile
.
An owner component "owns" the JSX of another component and can pass props into it.
Notice that UserProfile
could pass the user
state as props into ProfileLayout
and Avatar
if we wanted to. This is what makes UserProfile
an owner, the fact that it creates the JSX of these other components and could pass props to them.
In the hierarchy, UserProfile
and ProfileLayout
are "above" the Avatar
, but we have separate words for them because they are not the same. A parent component cannot pass props into the child. In our above example, ProfileLayout
is the parent of Avatar
and receives it as children
. Therefore it cannot pass props, therefore it's relationship to Avatar
is parent-child, not owner-child:
function ProfileLayout({ children }) {// We receive Avatar via children props, but we don't pass props into it}
Parents Don't Re-Render Their Children
You're probably aware that React can create a cascade of renders. When an owner component re-renders, it will re-render all the components it owns. This is not true of parent components. In our example, if UserProfile
re-renders for any reason, it will re-render both ProfileLayout
and Avatar
because it owns them.
function UserProfile() {const [user, setUser] = useState({})return (<ProfileLayout><Avatar /></ProfileLayout>)}
However, in a different scenario, if ProfileLayout
had state and it got a re-render, this would not create a re-render of Avatar
, even though Avatar
is "below" ProfileLayout
in the tree hierarchy:
function ProfileLayout({ children }) {const [someState, setSomeState] = useState()return <div>{children}</div>}
React Server Components
"Server components" are a new type of component in React. The term is confusing because we've always had the ability to run components on the server in terms of SSR. So then what do we call those other other kinds of components that we've been writing for years? We're starting to call them "client components" because they can run on the server but then can also run on the client. By contrast, server components cannot run on the client, they're server only.
If you're using server components with NextJS, you might notice that your component tree is server-components by default until you specify a client boundary for parts of the sub-tree. You can specify the use client
directive in a component and now all the components below it in the tree are client components. Lydia Hallie does a great job explaining these kinds of concepts with animations:
The reason why it's important to understand "owner vs parent" in React is because it will help you understand the new rules for using server and client components together.
Server components don't rehydrate to the client. They don't send their component code to the client at all. The results of a server component (HTML and other meta data) sit on the client statically without your component code being there in the client. Therefore they can't have state or JavaScript events and there's no concept of "re-rendering" for them - because again, there is no "component code" that goes to the client. This is why server components cannot be owned by client components -- because if a client component re-rendered on the client, there would be no way to "re-render" the server component it owns.
If we had written the examples like this where ProfileLayout
is a client component owner of Avatar
which is a server component, can you see how this would be a problem if ProfileLayout
got a re-render in the client? This would conceptually re-render Avatar
because ProfileLayout
is its owner. Since server components cannot be re-rendered, this is not allowed:
// Client Componentfunction ProfileLayout() {const [state, setState] = useState()return (<div><Avatar /></div>)}// Server Componentfunction Avatar() {}
If you need to render a server component under a client component (from a DOM perspective), you can do that but you have to re-arrange who owns what. In other words, make the server component UserProfile
own Avatar
and pass it in as children to the client component:
// Server Componentfunction UserProfile() {const user = getUser()return (<ProfileLayout><Avatar user={user} /></ProfileLayout>)}// Client Componentfunction ProfileLayout({ children }) {const [state, setState] = useState()return <div>{children}</div>}// Server Componentfunction Avatar({ user }) {}
Said another way, only server components can pass props into server components which we see above. When server components pass props to server components, this happens on the server before the HTML is created. Then when ProfileLayout
rehydrates and on the client, it can have state and re-renders.
Is the term unofficial?
I notice the React docs don't use owner very often. And sometimes they use "parent" in places that owner could have been used. I wish the term was more embraced officially because distinguishing between owner and parent really helps articulate what's happening in React better and I know my audience in workshops can understand more complex React concepts when I explain "owner" and then we can use that term conversationally.
If you search for the term on Google you'll see lots of older references to it.
https://www.google.com/search?q=owner+component+react
Every now and then I see the term "owner" being used so I hope when you see it, you'll have a better idea of what's being explained.