Passing Data to Components


this.props & this.state & Pure Components

Innovative Solutions and Technologies Center(ISTC)

Yerevan, Armenia

By Edgar Aroutiounian, Summer 2017

Progress:

Giving data to components


Assume that we have this component, the 'export default' makes it available to other ES6 modules

// This file is called banner.js
import React, { Component } from 'react';

class Banner extends Component {
  render() {
    return (
      <section>
        <h3>Some shopping cart</h3>
        <p>item1</p>
      </section>
    );
  }
}
export default Banner;

Giving data to components cont...


Say that this is the root of our application

import React from 'react';
import ReactDOM from 'react-dom';
import Banner from './banner';

// We ONLY need to call ReactDOM.render
// ONCE in our whole application
ReactDOM.render(<Banner />, document.getElementById('root'));

Here we made the Banner component and use the render function from the react-dom package to mount the React component tree into the DOM element we picked as the root of our React component tree.

Giving data to components cont...


Our Banner component doesn't get any data at the moment, it just is hardcoded to show one p tag. We can change that with using props.

<Banner
  bannerHeader={'Shopping Cart'}
  items={['shoes', 'hats']}/>

The bannerHeader and items that we passed in the JSX will be passed into the component and we can access them using the this.props property inside the component

Giving data to components cont...


We can use object destructuring to easily pick out the keys we want in this.props

render() {
  const { bannerHeader, items } = this.props;
  const cart_items = items.map(elem => {
    return <p key={elem}>{elem}</p>;
  });
  return (
    <section>
      <h3>{bannerHeader}</h3>
      {cart_items}
    </section>
  );
}

Notice that we can use an array of React elements in the return of render, also notice that we gave a key prop to the p element. This is so that we help the React diffing algorithm know which p elements to rerender when React needs to rerender based on new data. Do not use array index values as keys.

Meaning of this.props


Although this.props is just a plain object, it represents immutable data. It is data that is passed to a Component from another Component and we never mutate this.props because even if we did it would be meaningless as the next render will provide us with a new this.props.

Most applications though are not static, that is, their data changes over time and so we need a way to model that; for that we need to talk about state.

State in React


React Components also can hold state, that is data that changes over time.

class Cart extends React.Component {
  constructor() {
    super();
    this.state = { items: [] };
  }
}

Or in a faster way using class properties

class Cart extends React.Component {
  state = { items: [] };
}

Updating state (sort of)


The React API, aka the methods that we get when we extend Component, gives us a method called setState.

setState, which we call with this.setState takes two arguments, the first must be an object with key(s) which were the same as the original state object. The second parameter, which we usually omit, is a function callback. Often times though we only use the first parameter. After calling setState, React will queue up the update and update in this case means calling render again, but this time with the new state object.

We often use this.setState after we get data from the outside world, that is like data coming from the result of a fetch or user input

this.setState example


class GithubUser extends React.Component {
  state = { followers : 0 };
  componentDidMount() {
    fetch('https://api.github.com/users/fxfactorial')
    .then(req => req.json())
    .then(({followers}) => {
      this.setState({followers});
    })
  }
  render() {
    return <p> I have {this.state.followers}</p>;
  }
}

Props also get updated


React knows with its difference algorithm which Components need to be rerendered whenever any of the data that they depend changes/get updated, continuing with the last example

class Profile extends React.Component {
  render() {
    const { followers } = this.props;
    return <p> I have {followers}</p>;
  }
}

// and in the render method of GithubUser
render() {
  return <Profile followers={this.state.followers}/>;
}

Prefer Components with no state


We prefer to have Components that have no state and pass down to their child components whatever data they need via props.

Most software mistakes are because of state changing when we didn't expect it to change, hence making most Components only rely on this.props it easier to reason about our application. We control state changes with this.setState

Prefer functional components


Because we prefer to have Components with no state, we can use something called 'Functional Components'. These are just functions that return React elements without having to have first made a class. If your Component has no state, then prefer these instead of using class.

const Profile = ({followersCount, imgUri}) => {
  return (
    <div>
      <img href={imgUri}/>
      <p> I have {followersCount}</p>
    </div>
  );
};

Can be shorted as

const ProfileView = ({followersCount, imgUri}) => (
    <div>
      <img href={imgUri}/>
      <p> I have {followersCount}</p>
    </div>
);