React: "mount" vs "render"?
Learning something new can come with a bunch of new terms. So what's the difference between "mounting" and "rendering" in React?
See Our Public Workshops:
tldr;
- "Rendering" is any time a function component gets called (or a class-based
render
method gets called) which returns a set of instructions for creating DOM. - "Mounting" is when React "renders" the component for the first time and actually builds the initial DOM from those instructions.
A "re-render" is when React calls the function component again to get a new set of instructions on an already mounted component.
I'm starting to get this question about "mounting" vs "rendering" while teaching function components more often than I did with class-based components. I think I understand why. Let me explain "mounting" vs "rendering" with class-based components first and then we'll contrast it with the equivalent function component.
Let's assume App
is the first component React encounters since it's what we send to ReactDOM.render
class App extends React.Component {state = {showUser: false,}render() {return (<div>{this.state.showUser && <User name="Brad" />}<button onClick={() => this.setState({ showUser: true })}>Show User</button><button onClick={() => this.setState({ showUser: false })}>Hide User</button></div>)}}ReactDOM.render(<App />, document.getElementById('root'))
Internally, React will create an instance of App
and will eventually call the render
method to get the first set of instructions for what it needs to build in the DOM. Anytime React calls the render method of a class-based component, we call that a "render". Since this is the first time React is rendering this component, we also say the component is "mounting" -- in other words, React is taking that set of instructions and applying it to the DOM and this DOM did not exist already.
Then the user clicks the Show User button.
Anytime state changes, React will "re-render" the component. That just means it calls the render
method again to get new instructions based on the state change. In the case of our component above, this re-render will have showUser
as true
. With the value being true
now, the instructions returned from our component tell React that we need to make some DOM updates. The mounting phase was just during the first render so this second render is not also a mount, but rather we need to figure out what in the DOM will need to be updated. Internally, React knows how to compare the old instructions vs the new ones to see what actually needs to be updated in the DOM. This is called reconciliation.
The important takeaway so far is that the first "render" is going to lead to React "mounting" stuff to the DOM, and re-renders just update the DOM but don't mount since mounting just happens once.
<hr />Now lets rewrite this same code but with a function component and hooks:
function App() {const [showUser, setShowUser] = useState(false)return (<div>{showUser && <User name="Brad" />}<button onClick={() => setShowUser(true)}>Show User</button><button onClick={() => setShowUser(false)}>Hide User</button></div>)}
Function components also have renders and mounts. When a function component is used by React, the function gets called (rendered) and the instructions returned are used for the mount. So in a way it's almost like the entire function is similar to the render-method a class component -- even though we don't see the word "render" anywhere in the code like we did before.
Since function components can now have state (with hooks), the component will need to be re-rendered anytime state is changed just like before. With function components this just means the function is called again. As a mental model, you can think of it like this:
// React starts renders our component and since this is the// first render, it "mounts" the component to the DOM:App()// Then state changes and React now needs to re-render the// component with the new state in place:App()// State changes again, React re-renders again:App()
So as you can see, the first render which leads to mounting and re-renders are just calls to the function.
<hr />Now let's see how it works when we're discussing two components: User
and App
.
Each component will get its own schedule of mounting and re-renders that can differ from each other. Since User
is the child of App
, this will play a role as well.
From the beginning, React will render App
but since User
is not returned, it is unknown to React. So we could say that App
is mounted but User
is not.
Then when showUser
is set to true
, App
will get re-rendered which leads to returning instructions that include User
. Now User
gets rendered for the first time and mounted.
Then the user clicks the Hide User button.
State changed in App
so it will get re-rendered again. The new instructions returned from that re-render are compared with the ones from the previous render. React notices that User
(which was mounted) is not a part of the return from App
and so it "unmounts" User
from the DOM.
In component architecture, it's often true that parent nodes are aware of their children but children nodes are not aware of their parents. It's React's nature to re-render children nodes anytime there is a re-render in the parent. This is apart of what it means to be "reactive".
Even though each component has its own "schedule" of mounts and renders, the relationship between parent and child is such that a child component can only possibly render and mount if its parent is mounted. When a parent component unmounts, that will cause its children to unmount.