Understanding State and Props in React: Key Differences Explained

Understanding State and Props in React: Key Differences Explained

Are you new to React and feeling confused about the terms "state" and "props"? Fear not, because you're not alone! Even experienced developers can get tripped up by the differences between these two fundamental concepts in React.

In this article, you'll have a clear understanding of what state and props are, how they work, and, most importantly, how to use them in your own React projects.

How State Works in React

State in React - it's like the beating heart of your component. It's what makes your component dynamic and responsive. But what exactly is state, and how does it work in React? Let's break it down.

In simple terms, state in React is a JavaScript object that stores data about the component. This data can be anything from a string to an array to a complex object. React will automatically re-render the component when the state changes, updating the UI to reflect the new state.

State in React’s Class Component

Let's say you're building a simple React component that displays a counter. You might start by defining the initial state of the counter as 0. Here's an example of what that might look like:

import React from 'react';

class Counter extends React.Component {
	constructor(props) {
		super(props);
		this.state = { count: 0 };
	}

	render() {
		return (
			<div>
				<p>Count: {this.state.count}</p>
				<button onClick={() => this.setState({ count: this.state.count + 1 })}>
					Click me!
				</button>
			</div>
		);
	}
}

export default Counter;

In this example, a class-based component called Counter is defined. Inside the constructor, the counter's initial state is set to 0 using this.state = { count: 0 }. In the render method the current value of the counter is displayed using this.state.count.

Let's say you want to update the counter every time the user clicks the "Click me!" button. You can do that by using the setState method, which React provides. In this example, an arrow function is added to the button to update the count by incrementing it by 1.

When setState is called, React will update the component's state and re-render it with the new data.

While working with state, there are some common mistakes you'll want to avoid. One of the biggest is modifying the state directly, like this.state.count = 5.

Instead, you should always use the setState method to update state in React. Otherwise, React won't be able to detect the changes, and the component won't re-render correctly.

State in React’s Functional Component

State can be used in both class-based and functional components. Let’s explore the same example with a functional component.

In a functional component, state is handled using the useState hook. You can start by using the useState hook to define the counter's initial state as 0. Here's an example of what that might look like:

import { useState } from 'react';

function Counter() {
	const [count, setCount] = useState(0);

	return (
		<div>
			<p>Count: {count}</p>
			<button onClick={() => setCount(count + 1)}>Click me!</button>
		</div>
	);
}

export default Counter;

In this example, a functional component called Counter is defined. The useState hook define the counter's initial state as 0 using const [count, setCount] = useState(0).

Finally, the setCount method is used to update the state of the counter every time the user clicks the "Click me!" button.

Just like in class-based components, when working with state in functional components, it's important to avoid modifying the state directly. Always use the setCount method to update state in React.

Whether you're working with class-based or functional components, understanding how state works is crucial to building complex and dynamic React applications.

How Props Work in React

In React, props are another essential concept that works hand-in-hand with state. Props are short for "properties," and they're used to pass data between components.

Let's say you're building a simple React component that displays a greeting message. You might start by defining a prop called name that contains the name of the person you want to greet. Here's an example of what that might look like:

function Greeting(props) {
	return <h1>Hello, {props.name}!</h1>;
}

You can also decide to destructure the data:

function Greeting({ name }) {
	return <h1>Hello, {name}!</h1>;
}

In this example, a functional component called Greeting is defined. The component takes in a single prop called name using props.name. The component then uses the value of the name prop to display a greeting message.

Let's say you want to use this component in another part of your application. You can pass a value for the name prop by rendering the Greeting component and passing the name value as an attribute. Here's an example of what that might look like:

<Greeting name="John" />

In this example, you're passing a value of "John" for the name prop.

When working with props, there are some common mistakes you'll want to avoid. One of the most common is forgetting to define a default value for a prop. If a prop is not passed a value, the component will throw an error. To avoid this, you can define a default value for a prop using defaultProps.

function Greeting(props) {
	return <h1>Hello, {props.name}!</h1>;
}

Greeting.defaultProps = {
	name: 'World',
};

In this example, a default prop value of "World" for the name prop is defined using Greeting.defaultProps = { name: "World" };. If the name prop is not passed a value when the component is rendered, it will default to "World."

Another mistake to avoid is modifying props directly within a component. Just like with state, you should always treat props as read-only. If you need to modify the value of a prop, create a new variable within the component and modify that instead.

function Greeting(props) {
	const modifiedName = props.name.toUpperCase();

	return <h1>Hello, {modifiedName}!</h1>;
}

In this example, you've created a new variable called modifiedName within the Greeting component that uses the toUpperCase() method to modify the value of the name prop. You then use the modifiedName variable to display the greeting message.

By creating a new variable instead of modifying the name prop directly, you can ensure that the prop remains read-only and that the component is more predictable and easier to maintain.

Differences between State and Props in React

Let's dive into the key differences between state and props in React. While both state and props are used to manage data in React components, there are some important distinctions between the two.

  1. State is managed within a component, while props are passed down from parent to child components. In other words, state is internal to a component, while props are external.
  2. State can be modified within a component using the setState method, while props are read-only and cannot be modified within a component.

So, when should you use state and when should you use props?

Here's a rule of thumb: if a value is going to change within a component, it should be managed with state.

If a value is going to remain constant within a component but needs to be passed down to child components, it should be passed as a prop.

Let's take a look at some real-world examples to illustrate this. Imagine you're building a simple counter app with React. The current count value is going to change within the component as the user clicks a button, so it should be managed with state:

import { useState } from 'react';

const Counter = () => {
	const [count, setCount] = useState(0);

	const incrementCount = () => {
		setCount(count + 1);
	};

	return (
		<div>
			<h1>Count: {count}</h1>
			<button onClick={incrementCount}>Increment</button>
		</div>
	);
};

export default Counter;

On the other hand, imagine you're building a component that displays a user's profile picture and name. The user's name is going to remain constant within the component but needs to be passed down to child components, so it should be passed as a prop:

import Bio from './Bio';

const UserProfile = (props) => {
	return (
		<div>
			<img src={props.profilePicture} alt="Profile picture" />
			<h1>{props.name}</h1>
			<Bio bioText={props.bioText} />
		</div>
	);
};

export default UserProfile;

In this example, the name prop is passed down to the Bio component, where it's used to display the user's bio text.

Conclusion

Congratulations! You've made it to the end of this article on state and props in React. By now, you should have a solid understanding of what state and props are, their key differences, and how to use them effectively in your React components.

Understanding the differences between state and props is crucial for building effective and maintainable React components. By knowing when to use state and when to use props, you can create components that are more modular, flexible, and easier to reason about.

Try what you have learned in the interactive code editor below.

import { useState } from 'react';

function App() {
const [count, setCount] = useState(0);

    return (
    	<div>
    		<p>Count: {count}</p>
    		<button onClick={() => setCount(count + 1)}>Click me!</button>
    	</div>
    );

}

export default App;

Have fun coding!


Joel Olawanle

Written by Joel Olawanle

Joel is a software engineer and teacher. He write's about software development, productivity, and life. He has written over 150 technical content that has helped millions of people all over the world.


Previous Post

Slice vs. Splice in JavaScript: Understanding the Differences and When to Use Them

In this article, we'll explore the differences between slice and splice, and provide you with some exciting code examples to help you understand how t...

Next Post

Recursion in JavaScript: Explained for Beginners

In this article, we'll explore the differences between slice and splice, and provide you with some exciting code examples to help you understand how t...