React.js Tutorial: State And Props

 ·  · 

Explanation of how React component manipulate data using state and props (properties).

 

1 What is state and props

State, in React component, is internal dataset which affects the rendering of the component. To some extent state can be considered as the private data or data model of React components.

React component state is mutable. Once the internal state of a React component is changed, the component will re-render itself according to the new state.

Props, which is short for properties, are properties of React component. Props look like HTML attributes. Values of props in a React component are commonly passed from the parent component.

Props are just passed into, so props are immutable in the eyes of the child components and shouldn't be changed directly by the child components.

reactjs-state-and-props

 

2 Initialization of state

React.js provided getInitialState() method to initialize the state of a component in ES5 (ECMAScript 5).

var PetsList = React.creatClass({
    getInitialState: function () {
        return {
            pets: pets
        }
    },
    render: function () {}
});

However, it's better to set initial state value in the constructor of a component in ES6.

class PetsList extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            pets: pets
        };
    }
    render () {}
}

 

3 Default props

getDefaultProps() is the place to give default values of component props in ES5.

var SinglePet = React.creatClass({
    getDefaultProps: function () {
        return {
            name: 'empty',
            image: './images/default_avatar.png'
        }
    },
    render: function () {}
});

There are two ways to set default props in ES6 syntax.

The first way, and also the recommended way, is to use static member of the ES6 class.

class SinglePet extends React.Component {
    static defaultProps = {
        name: 'empty',
        image: './images/default_avatar.png'
    }
    render () {}
}

But inheritance of the static member of ES6 class will only work in IE11+. If your React components use inheritance and are going to run in IE11-, above codes won't work.

The second way is to set a defaultProps directly to the component class.

class SinglePet extends React.Component {
    render () {}
}

SinglePet.defaultProps = {
    name: 'empty',
    image: './images/default_avatar.png'    
}

 

4 Simple Demo

I'd like to give a simple demo project to show how state and props work in React components.

Main feature of this simple demo project are as follows:

  1. A PetsList component will hold data of four pet animals by its state;
  2. The PetsList component will pass detail information of a single pet to a SinglePet component via props.
  3. The SinglePet component will display every pet in detail separately.
  4. By default the PetList component will list all animals.
    • If "Dogs" button is clicked, only dogs will be listed;
    • If "Cats" button is clicked, only cats will be listed;

reactjs-state-and-props-demo-ui

4.1 Project structure

Firstly, create folder structure of the demo project.

reactjs-state-and-props-demo-structure

4.2 index.html

Secondly, create a entry html file of the demo project.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>React State And Props Demo</title>

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" charset="utf-8">

    <!-- react includes two parts: react.js and react-dom.js -->
    <script src="//fb.me/react-15.2.1.js"></script>
    <script src="//fb.me/react-dom-15.2.1.js"></script>

    <!-- babel standalone -->
    <script src="//cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.10.3/babel.min.js"></script>
</head>
<body>
    <div id="app" class="container"></div>

    <script type="text/babel" src="./react-state-props.js"></script>
</body>
</html>

Note that I will use handy CSS styles of Bootstrap for simplicity.

4.3 Sample Data

Prepare the JSON data of pet animals, two dogs and two cats.

/* react-state-props.js */

/* json data */
const pets =  [
    {
        'name': 'Ailu',
        'kind': 'dog',
        'image': './images/dog-1.png',
        'desc': 'Ailu like swimming!'
    },
    {
        'name': 'Bilu',
        'kind': 'dog',
        'image': './images/dog-2.png',
        'desc': 'Bilu has beautiful eyes!'
    },
    {
        'name': 'Luta',
        'kind': 'cat',
        'image': './images/cat-1.png',
        'desc': 'Luta like palying ball!'
    },
    {
        'name': 'Kuta',
        'kind': 'cat',
        'image': './images/cat-2.png',
        'desc': 'Kuta does not eat pizza!'
    }
];

4.4 Components

PetsList component will be responsible for manipulating pets data and rendering data items with SinglePet child component.

/* react-state-props.js */

/* json data */
// ... 

/* components */
class SinglePet extends React.Component {
    constructor(props) {
        console.log(props);
        super(props);
    }
    render () {
        return (
            <div>
                <h3>{this.props.name}</h3>
                <img src={this.props.image} alt=""/>
                <p>{this.props.desc}</p>
            </div>
        )
    }
}

class PetsList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            pets: pets
        };
    }
    render () {
        return (
            <div>
                <h3>Pets List: </h3>
                {
                    this.state.pets.map((v,idx) => {
                        return <SinglePet key={idx} name={v.name} image={v.image} desc={v.desc} />
                    })
                }
            </div>
        )
    }
}

Following figure will give a summary of the role of state and props.

reactjs-state-and-props-demo

Mount the PetsList component.

/* react-state-props.js */

/* json data */
// ... 

/* components */
// ... 

/* Main app component */
class App extends React.Component {
    render () {
        return (
            <div>
                <h1>React State And Props Demo</h1>
                <PetsList />
            </div>
        )
    }
}

// Mount root App component
ReactDOM.render(<App />, document.getElementById('app'));

Now access the demo project by URL: http://<YOUR_SEVER>/react-state-props/index.html, you can see four pets will be listed, two dogs and two cats.

4.5 Change state

Add three filter buttons to the PetsList component and create a response function to handle filter button clicking event.

/* react-state-props.js */

// ...

class PetsList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            pets: pets
        };
    }

    // Handle button clicking
    clickToFilter (kind) {
        let animals = [];

        if (kind === 'all') {
            animals = pets;
        } else {
            animals = pets.filter(v => {
                if (v.kind === kind) {
                    return true;
                }
            });
        }

        // Change state
        this.setState({ pets: animals });
    }
    render () {
        return (
            <div>
                <h3>Pets List: </h3>
                <button onClick={ this.clickToFilter.bind(this, 'all') }>All</button>
                <button onClick={ this.clickToFilter.bind(this, 'dog') }>Dogs</button>
                <button onClick={ this.clickToFilter.bind(this, 'cat') }>Cats</button>
                {
                    this.state.pets.map((v,idx) => {
                        return <SinglePet key={idx} name={v.name} image={v.image} desc={v.desc} />
                    })
                }
            </div>
        )
    }
}

// ...

When the state data is changed by calling this.setState(), the render() function will be called automatically to re-render the changes in state.