It will use this.setState() to schedule updates to the component local state: The render method will be called each time an update happens, but as long as we render <Clock /> into the same DOM node, only a single instance of the Clock class will be used. This lets us use additional features such as local state and lifecycle methods. React then calls the Clock component’s render() method. This is how React learns what should be displayed on the screen. React then updates the DOM to match the Clock’s render output.
this.setState({
newState: 'whatever'
},
() => {
/*do something after the state has been updated*/ }
)
const root = ReactDOM.createRoot(document.getElementById('root'));
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
root.render(element);}
setInterval(tick, 1000);
const root = ReactDOM.createRoot(document.getElementById('root'));
function Clock(props) {
return (
<div> <h1>Hello, world!</h1> <h2>It is {props.date.toLocaleTimeString()}.</h2> </div> );
}
function tick() {
root.render(<Clock date={new Date()} />);}
setInterval(tick, 1000);
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div>
);
}
}
As we already saw before, React re-renders a component when you call the setState function to change the state (or the provided function from the useState hook in function components). It's important to change the state with the corresponding React functions. You can find the Codepen here. The first one, which I already gave away before, is React.memo. I already wrote a more in-depth article on this, but in summary, it's a function that prevents your React Hook components from rendering when the props don't change.
const App = () => {
const [message, setMessage] = React.useState('');
return (
<>
<Tile message={message} />
<Tile />
</>
);
};
this.props.user.name = 'Felix';
const Parent = () => {
const [user, setUser] = React.useState({ name: 'Felix' }); const handleInput = (e) => {
e.preventDefault();
setUser({ ...user, name: e.target.value, }); };
return (
<>
<input onChange={handleInput} value={user.name} />
<Child user={user} />
</>
);
};
const Child = ({ user }) => (
<h1>{user.name}</h1>
);
const [state, updateState] = React.useState();
const forceUpdate = React.useCallback(() => updateState({}), []);
const TileMemo = React.memo(({ children }) => { let updates = React.useRef(0);
return (
<div className="black-tile">
Memo
<Updates updates={updates.current++} />
{children}
</div>
);
});
Calling setState() here makes it possible for a component to produce infinite loops. The render() function should be pure, meaning that it does not modify a component’s state. It returns the same result each time it’s invoked, and it does not directly interact with the browser. A component can have an initial state set, access it, and update it. In the code block below, we are setting the component’s initial state. This is done through the constructor method:
Components that have a state are referred to as stateful components, while those that do not have states are stateless components.
import React, {
Component
} from 'react';
class Food extends Component {
constructor(props) {
super(props)
this.state = {
fruits: ['apple', 'orange'],
count: 0
}
}
}
Because states are plain JavaScript objects, this.state
must be equal to an object:
this.state = {
fruits: ['apple', 'orange'],
count: 0
}
Avoid confusing the state
object with other instance properties. It’s easy to assume you can define another object in the constructor and try to use it like state
, but the state
instance is a special one because React manages it:
...
//constructor function above
this.state = {
fruits: ['apple', 'orange'],
count: 0
}
this.user = {
name: 'Obaseki Nosa'
}
...
Use the setState()
method everywhere else; doing so accepts an object that eventually merges into the component’s existing state.
For example, the following does not rerender a component:
// Wrong
this.state.name = 'Obaseki Nosa';
The setState()
schedule changes to the component’s state object and tells React that the component and its children must rerender with the updated state:
// Correct
this.setState({
name: 'Obaseki Nosa'
});
React programmers usually update state by passing an object that describes the changes we'd like to make. React then assigns the values and triggers an update. But what if I told you that you can pass a function to setState()? That's right, there's a functional side to React. Well, you can now prevent state updates and re-renders straight from setState(). You just need to have your function return null. For example, there is a maximum number of pizzas I can eat before I pass out. We don't want to continue updating and re-rendering after that point. There are many ways you can prevent that in React, but here's how you do it with functional setState(): This means you can decouple the state update logic from your components and export it to a new file to make it reusable and declarative. Sweet!
Here's how it works: You pass a function to setState()
that takes state
and props
as parameters and returns your desired state, which React will then use for the update. We go from this:
// Increase the numbers of pizzas I need to eat
this.setState({
pizzas: this.state.pizzas + 1
});
To this:
// Increase the number of pizzas I need to eat
function addAnotherPizza(state, props) {
return {
pizza: state.pizza + 1,
}
}
this.setState(addAnotherPizza);
const MAX_PIZZAS = 20;
function addAnotherPizza(state, props) {
// Stop updates and re-renders if I've had enough pizzas
if (state.pizza === MAX_PIZZAS) {
return null;
}
// If not, keep the pizzas coming
return {
pizza: state.pizza + 1,
}
}
this.setState(addAnotherPizza);
Update in state: The state change can be from a prop or setState change to update a variable(say). The component gets the updated state and React re-renders the component to reflect the change on the app. Update in prop: Likewise the change in prop leads to state change and state change leads to re-rendering of the component by React. React schedules a render every time state changes (scheduling a render doesn’t mean this happens immediately, this might take time and be done at the best moment). Changing a state means React triggers an update when we call the useState function (useState is a Hook that allows you to have state variables in functional components).
Example: Creating a simple Counter React Project will help to understand the concept of re-rendering components.
Prerequisite: Download VS Code and Node packages.
Step 1: Create a new React project named counter-app by running the below given command.
npx create - react - app counter - app
Step 2: Once the installation is done, you can open the project folder as shown below.
cd counter - app
Step 3: After creating the React JS application, install the required module by running the below given command.
npm install react - desktop
The code gives a message each time the component’s render function is called. Each time the count button is clicked state change is triggered. Each state change in the parent component triggers re-rendering of all its subsequent child components even if no props are changed.
Child.js
function Child(props){
console.log("Child Rendered");
return(
<div>
<h1>Child Name={props.name}</h1>
</div>
);
}
export default Child;
Step to run the application: Open the terminal and type the following command.
npm start
It is worth noting that following a props update or setState(), the method shouldComponentUpdate() is invoked to determine whether render() should be called. By default, this method always returns true. But it can be overloaded to implement custom logic. It is the actual way to define custom render behavior in each React component. The shouldComponentUpdate() provides you with nextProp and nextState as arguments, which allows you to compare the current state and props of the component. For example, this code block will invoke render() only when the text prop changes: Clicking button 1 will update the childElementText state of the Parent component, which in turns updates the text prop of the Child component, triggering a render in both Parent and Child.
The dotted border line distinguishes between elements that belong to the Child component of the example (inside the dotted line) versus the Parent component.
onChildPropChange = () => {
this.setState({
childElementText: "I am the child element! I am updated following a prop change."
})
}
onTextChange = () => {
this.setState({
helloWorldMessage: "Hello React! (state change after setState call)"
})
}
shouldComponentUpdate(nextProps: NewComponentProps, nextState: NewComponentState) {
if (this.props.text !== nextProps.text) {
return true;
} else {
return false;
}
}
If a <NewComponent>
is then added to the top of the list:
<div>
<!-- previously <span>list item 1</span> - element is detached and <NewComponent /> instantiated -->
<NewComponent />
<!-- previously <span>list item 2</span> - content will be updated to "list item 1" -->
<span>list item 1</span>
<!-- previously <span>list item 3</span> - content will be updated to "list item 2" -->
<span>list item 2</span>
<!-- new <span>list item 3</span> is element created -->
<span>list item 3</span>
</div>
If instead <NewComponent>
is added to the bottom:
<div>
<!-- previously <span>list item 1</span> - no change -->
<span>list item 1</span>
<!-- previously <span>list item 2</span> - no change -->
<span>list item 2</span>
<!-- previously <span>list item 3</span> - no change -->
<span>list item 3</span>
<!-- new instance of <NewComponent /> is added -->
<NewComponent />
</div>