Component Props and State

  1. Props:

    • Similar to arguments of a function
    • Are immutable once passed in
    • Can be passed down to children explicitely
  2. State:

    • Private data held within the Component
    • Can be updated using setState({someNew: 'data'}) or the updater from useState
    • Must be updated from the object that owns it
    • Can be passed down to children as Props
    • Can be updated by children by passing functions

Stateless Functional Components

<body>
  <div id="root"/>
</body>
<script>
  /* This is a perfectly valid React Component*/
  const HelloThere = (props) => {
    return <h1>Hello, { props.name }</h1>
  }

  ReactDom.render(<HelloThere name="Grace Hopper"/>,
    document.getElementById('root')
  )
</script>
<body>
  <div id="root">
    <!-- This is what the code would result in -->
    <h1>Hello, Grace Hopper</h1>
  </div>
</body>

All Props are Immutable

/* Always returns the same JSX for given inputs */

function UserInfo (props) {
  return (
    <div className="UserInfo">
      <Avatar user={ props.user } />
      <div className="UserInfo-name">
        { props.user.name }
      </div>
    </div>
  );
}

Pure and Impure Functions

/* This is a 'Pure' function */
/* It always returns the same output for given inputs */

function sum (first, second) {
  return first + second;
}
/* This is an 'Impure' function */
/* It can return different things based on the balance */

function deduct (bankAccount, amount) {
  bankAccount.balance = bankAccount.balance - amount;
  return bankAccount
}

Component State

Description

Rules

Props vs State

State - Tick Live

See the Pen React Clock Example by Joshua Burke (@Dangeranger) on CodePen.

State - Tick Code

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(
    element,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

State - Extract Component

Does this use component state?

/* Now we have a component */
function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

/* Use the component in a function */
function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

State - Convert to Class

/* From this */
function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

/* To this */
class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

State - Start the Clock

class Clock extends React.Component {
  constructor(props) {
    /* Make sure to call super in a constructor */
    super(props);
    /* Setting the initial state */
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <!-- Use the state instead of props -->
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

State - Manage the Clock

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

State - Working Clock

See the Pen Hello World in React by Joshua Burke (@Dangeranger) on CodePen.

State - Remember

/* Not good */
this.state.comment = 'Hello';

/* Excellent */
this.setState({comment: 'Hello'});

Lab: Color Clicker

Let's create a new react project that has a button you can click to change the color of some text.

State - Updates can be Async

/* Incorrect */
this.setState({
  counter: this.state.counter + this.props.increment,
});

/* Super Great */
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

State - Updates are Merged

constructor(props) {
  super(props);
  this.state = {
    posts: [],
    comments: []
  };
}

componentDidMount() {
  fetchPosts().then(response => {
    this.setState({
      posts: response.posts
    });
  });

  fetchComments().then(response => {
    this.setState({
      comments: response.comments
    });
  });
}

State - Many Clocks

See the Pen Hello World in React by Joshua Burke (@Dangeranger) on CodePen.

Using Functional Component Syntax

Instead of creating a Component by extending the Component class we can write a function like this:

function StatelessComponent (props) {
  return <h1>Hello {props.name}</h1>
}

Then we can slot it into a stateful component like so:

class Stateful extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name: "Bill"};
  }

  render() {
    return (
      <div>
        <StatelessComponent name={this.state.name} />
      </div>
    );
  }
}

We could also slot it into another stateless component and pass props directly to it:

function AlsoStateless (props) {
  return (
    <div>
      <StatelessComponent name="Bob" />
    </div>
  )
}

 Previous Next 

Outline

[menu]

/