What Is The Difference Between State And Props In React?

Flatlogic Platform
Flatlogic
Published in
10 min readJun 24, 2021

Learning React starts with several concepts developers run into — JSX syntax, props, and state. State is a familiar concept for developers, while JSX syntax and props confuse new people in React because they are never mentioned in any other web frameworks. JSX syntax is optional and you can develop apps in React without that syntax (however, JSX makes the development process much easier after learning it). On the other hand, props and state are one of the most important topics when learning React. Props provide communication between components while state expands the possibilities of your app beyond the display of static content.

First, we refer to the state and props definitions, then look at two different types of components: stateful and stateless. People who are in search of a fast answer can jump straight into a brief comparison abstract and look through the table with briefing memos about the differences between state and props.

Enjoy reading!

Props and state definition

Props are a JavaScript object that React components receive as an arbitrary input to produce a React element. They provide a data flow between the components. To pass the data (props) from one component to another as a parameter:

For a class component you need to define the custom HTML attributes to which you assign your data and then pass it with special React JSX syntax:

import React, { Component } from 'react';   
class App extends Component {
render() {
const greeting = 'Welcome to React';
return (
<div>
<Greeting greeting={greeting} />
</div>
);
}
}
class Greeting extends Component {
render() {
return <h1>{this.props.greeting}</h1>;
}
}
export default App;

To receive props class components need to use JavaScript keyword this.

For a functional component props are passed as an argument to a function:

import React, { Component } from 'react';   
class App extends Component {
render() {
const greeting = 'Welcome to React';
return (
<div>
<Greeting greeting={greeting} />
</div>
);
}
}
const Greeting = props => <h1>{props.greeting}</h1>;
// here an arrow function receives props with the name greetings export default App;

In our example, our data was a string variable. But props can be anything: integers, objects, arrays, and even React components.

State:

State is a JavaScript object which contains data that influence how the component looks at a certain point in time. The second part is what makes the state different compared to props. State is just a snapshot of the app in a time. Every user interaction with your app may lead to changes in the underlying state and in the whole UI as a result. State changes over the lifetime of a React component. Examples of state:

For a class component you need to call the class constructor inside the React component:

import React, { Component } from 'react';   
class Button extends Component {
constructor(props) {
super(props);
this.state = { counter: 1 };
}
render() {
return (
<button>{this.state.counter}</button>
);
}
}
export default Button;

For a functional component you need to use useState Hook:

import React from 'react';   
function Counter() {
const [count, setCount] = React.useState(1);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Counter;

State breathes life into your application and is a thing that makes your application dynamic and interactive. State could be Boolean, integers, strings, or complex JavaScript objects.

Stateful and stateless components

Stateless Component may contain only props, no state. Such a component can be associated with a function: it receives input ( ‘props’ object) and returns the result (React element). Stateless components are used when you want to represent the props and the component doesn’t need to be interactive. They are easy to use and easy to test.

Stateful Component may contain props but has to have state. A stateful component owns its state and can change it. When the component changes state, it re-renders. Statefulcomponents help when the app needs to respond to user input and actions. They provide a dynamic user interface through client-server communication and help to create interactive pages. Traditionally functional components are stateless, while class components feature manipulations with state. However, it has changed with the introduction of Hooks for functional components. State was one of the key advantages of class components, but nowadays Hooks added state management and lifecycle methods to functional components, so they are also can be called stateful components. You can read more about class and functional components in this article.

Brief comparison

Let’s begin with facts that are common both for props and state.

  • React components re-render if props or state have changed. Any update from anywhere in the code triggers an automatic re-render of the appropriate part of the User Interface.
  • Props and state are JS objects, which means they both contain as many properties and methods as we need.
  • The same combination of props and state must produce the same output. This type of component is deterministic.

State vs. props — detailed comparison

State has to have the initial value, while props can be empty

State can’t exist without the initial value. When the component becomes stateful you need to declare the first value of state directly.

In class components using constructor():

class CalmDown extends React.Component {   
constructor(props) {
super(props);
this.state = {
currentState: "not-panic",
}
}
}

In functional component we set the initial value via Hook useState()

import { useState } from 'react';   
function TimeToPanic() {
// Declare a new state variable, which we'll call "mood"
const [mood, changeMood] = useState(‘calm’); // we declare a new state variable “mood” with the initial value equal to 0
return (
<div>
<p>You feel {mood}</p>
<button onClick={() => changeMood(mood=’the panic’)}>
Click me
</button>
</div>
);
}

In the example above changeMood is a method that allows us to update the mood’s state. The component can get the initial state from the parent component. The initial state for props is not a necessary staff. We can pass an empty value or set the default value when the props are empty.

function CatComponent(props) {    
return <div>{props.catName} Cat, Eye Color: {props.eyeColor}, Age: {props.age}</div>
}
CatComponent.defaultProps = {
catName: "Sandy",
eyeColor: "deep blue",
age: "120"
}
const cat = <CatComponent catName="Milk"/>

CatComponent renders the following string: “Milk Cat, Eye Color: deep blue, Age: 120”. Since we pass empty values for props attributes eyeColor and age the component uses the default values for them, while the attribute catName returns the value we have previously assigned. If CatComponent is called without the default values, it will simply render “Milk Cat, Eye Color: , Age:”

Both props and state initial values received from parents override default values defined inside a Component.

Props are immutable, while state is mutable

One significant limit to props is that they are read-only from inside the component. There is no way in React for a component to set a new value for its incoming props. That brings us to the concept of pure components that don’t change their inputs and return the same result for the same props. Trying to change the props will throw an error, so the following block of code will not work:

function Add(props) {  
if (typeof props.n2 === 'undefined') {
props.n2 = 0
}
return (
<div>
{props.n1} + {props.n2} = {props.n1 + props.n2}
</div>
)
} // TypeError: Cannot add property n2, object is not extensible

That is totally consistent with the role props play: they just pass data from component to component. Although a component is not allowed to change its props, it is responsible for the props of its child components down the component tree.

On the other hand, state is mutable. A stateful component changes its state every time users interact with the app. Furthermore, a stateful component is responsible for management only its own state and has no impact on child components (a parent component can only set the initial state of its children components, we discuss it further below). We can say that stateof every component is private. There are some rules on how to use and modify statecorrectly:

  • No direct modification: command this.state.name = ‘me’; is allowed only for the initial initialization of state, in render() method we need to use setState()
  • State updates may be asynchronous setState() callbacks all happen together at the end of the state update phase in React, not immediately after that particular update happens. That may lead to confusion.

The role state and props play

Here we come to the difference in concepts of these two objects.

The role of state:

  • Make the components interactive
  • Provide users with an opportunity to modify the state
  • Track data values over the lifetime of the component
  • Update the UI when the state has been changed
  • React when the time passes (interval or timeout)

The role of props:

  • To display static non-interactive components and data
  • To pass data from a component to component

An additional role of state that should be mentioned is fetching remote data. The component fetch data after it is mounted, so state allows us to update the component once the data from a third-party resource comes.

State can be passed as props to child components

The state of one component can be passed as a prop to child components. There is no difference for the child component whether the incoming prop is state of the parent components or a simple prop. The component gets the data and uses it in rendering — that is all. If the incoming props change (doesn’t matter because of the changes in parent component state or because the props were changed) the child component re-renders.So props and state are interrelated. We can pass state as props within the rendermethod of the parent component:

class CalmDown extends React.Component {   
constructor(props) {
super(props);
this.state = {
currentState: "do not panic",
}
}
render() {
return <div>Just remember: {this.state.currentState}</div>;
<MyChild mood = {this.state.currentState}/>
}
}
class MyChild extends React.Component {
return <h1>Hello! I {this.props.mood}</h1>;
}
}
}

The parent’s state value of currentState becomes the child’s this.props.mood. For MyChild component mood props is immutable. If we need to change the props in the child component, we need to change the state in the parent component:

this.setState({ currentState: ‘PANIC!’})

And then React passes the new value to MyChild component and re-render both elements.

If we want to change the name of the prop, we should create a child event and parent callback. Guess that we have an event called onNameChanged in the child that passes newMood as an argument to the event callback. Let add a callback handler and the event handler to the parent:

MyChild mood ={this.state.currentState} onNameChanged={this.handleMood} /> 
handleMood: function(newMood) {
this.setState({ currentState: newMood });
}

And then we set a new name for child prop. We didn’t bend the rule that data should go from parent components to child components (downwards). The mood prop is managed by the parent CalmDown component, only the parent can change the prop for child components and pass it once again. Basically, it is the way how React components communicate with each other and how props are passed. They go downwards from parent to child components. And the state of the parent can become the prop of the child.

Usage of state and props in higher-order components

To build a higher-order class component we have to use state, while the same component in terms of functionality that is built with functional components requires props only.

Higher-order components are functions that take a component as an input and transform it not into UI, but another component.

Let’s build a login higher-order class component with a form where we input email and password and the component returns the answer whether such a user is registered in the app or not.

import React from 'react'; 
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
class Example extends React.Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
};
constructor(props) {
super(props);
this.state = {
email: 'admin@flatlogic.com',
password: 'password',
};
this.doLogin = this.doLogin.bind(this);
}
doLogin(e) {
e.preventDefault();
this.props.dispatch(loginUser({ email: this.state.email, password: this.state.password }));
}
isLogin () {
return this.props.isAuthenticated
}
render() {
return (
<form onSubmit={this.doLogin}>
<button type="submit">Login</button>
</form>
);
}
}
function mapStateToProps(state) {
return {
isAuthenticated: state.auth.isAuthenticated,
};
}
export default withRouter(connect(mapStateToProps)(Login)); functional components:

We use state to take user input data and only after that step can we call the higher-order function isAuthenticated with state as an argument.

Let’s examine exactly the same component in terms of functionality, but built using propsonly:

import React from "react";
import { useDispatch, useSelector } from "react-redux";

const Login = () => {
const dispatch = useDispatch(); const isAuth = useSelector(store => store.auth.isAuth)


const doLogin = () => {
if (isAuth) {
// some async logic
}
}

return (
<form onSubmit={() => dispatch(doLogin())}>
<button type="submit">Login</button>
</form>
);
};

export default Login;

Our new component has fewer lines of code but provides the same functionality. Thus, to make a login form we have to build higher-order functions with state in class components. In functional components we use Hook useDispatch() and constants (props).

So when to use state and props?

Hope that we shed some light on the difference between the two React concepts. However, there is one more question left:

When are we supposed to use props and when resort to state?

Some basic rules:

  1. Components without state are preferable. State increases the common complexity of the app, makes the render result less predictable and testing less steady. Although you can’t avoid using state in the app because state is the basis for building interactive apps in React, just make sure that your app has as many Stateful components as possible.
  2. A wide-spread pattern of building apps is to make several stateful components on top of the hierarchy and create stateless components under them, passing all necessary information and staff via props from parents to child components. The point here is to isolate the logic of interaction on the top of the app in parent statefulcomponents and to transfer the responsibility of rendering data to child statelesscomponents.

When we should use stateless components:

  1. When we need to display the data
  2. When we build a non-interactive element in the UI
  3. When we have a stateful component above, we should check whether it’s possible to use state from above rather than introduce a new local state

When we should use stateful components:

  1. When the component is supposed to accept user input
  2. When we build an interactive UI element
  3. When the component needs to work with data that it can’t get as props from parent components
  4. When we work with fetching data

Thanks for reading!

About Flatlogic

At Flatlogic we develop web & mobile templates. We are listed among Top 20 Web Development companies from Belarus and Lithuania. During the last years, we have successfully completed more than 50 big projects for small startups and large enterprises.
Flatlogic templates
Flatlogic case studies

Here is a short video about Flatlogic templates, web development services, and an affiliate program.

Originally published at flatlogic.com — React, Angular, Vue, Bootstrap & React Native templates, and themes.

Text source: https://flatlogic.com/blog/what-is-the-difference-between-state-and-props-in-react/

--

--

Flatlogic Platform
Flatlogic

Flatlogic is an AI-powered platform for creating Enterprise Business Apps. Save 250+ hours by generating full-stack web app or choosing from dozens of templates