about code ¯\_(ツ)_/¯

Data and React components

The post second in this series on React. We focus on how data flows in and out of a React component and how you can use this data to connect multiple components together to build an app.

Building a Stateful React component

We’re gonna walk though building a React component with state like the video player component in the image below. The component changes rom a image thumbnail to a video player when clicked.

Video Player

Photo by William Hook on Unsplash

State of the world

What is state? State is the data that’s needed by a component to look and behave a cetain way. In our previous (getting started) example the component got all it’s data through properties. But what if component needed to remember something itself

Our old friend the Image component

const Image = (props) => (
  <div className='image'>
  <img src={props.src} height={200} />
  ...
  </div>
)

Now what if we had a series of images and everytime you clicked on the image it would display the next one. Yes, this would now require the image component’s src property to accept a list of images instead of just one. And the component would have to remember which of the images it’s currently displaying so it can move to the next one when clicked.

Having to remember the current displayed image is the state of the image component.

class Image extends React.Component {
  constructor(props)  {
    super(props)
    this.state = { currentImage: 0 }
  }

  imageClk =() => this.setState({ currentImage: this.state.currentImage + 1})
  
  render() {
    <div className='image'>
    <img 
      onClick={this.imageClk}
      src={props.src[this.state.currentImage]} 
      height={200} />
    ...
    </div>
  }
}

Wow, thats looks like a big change, what happened to my simple component. Calm down it’s not what you think let me explain. Without state you had a pure-component (aka. functional-component) which is essentially just a single function. And with state our little component had to grow up and and become a class. For those that don’t know a class is just a collection of funtions and data that can all work together.

In our case this has to be a React.component class hence the extends. If you want to learn more about classes (ES6 classes) read the Mozilla docs.

constructor(props)  {
  super(props)
  this.state = { currentImage: 0 }
}

This is how you make properties work with component that have state (stateful components). Since the constructor is the first thing that’s called when the component startups it’s also the place to setup the initial state.

imageClk = () => this.setState({ currentImage: this.state.currentImage + 1})
  
render() {
  <div className='image'>
  <img 
    onClick={this.imageClk}
    src={this.props.src[this.state.currentImage]} 
    height={200} />
  ...
  </div>
}

The imageClicked function is called everytime the image is clicked on and it upates the state moving the currentImage number up by one. Yes, I know eventually it will go past the number of images we have to show but I’m trying to keep things simple here for now so ignore that.

Also remember props.src is will not be this.props.src and that goes for state too it’s this.state everywhere. Why? It just is!

😲 Do not change state directly!

The only way to change or update your component state is using this.setState. There is no other way you must not directly try and change specific items inside state without using setState.

state = { a: 1, b: 2 }

Lets pretent this above is the state of your component. The follow attempt at changing is wrong and won’t work. It does not use setState so that’s a no-no.

/* This is wrong and won't work */

this.state.a = this.state.a + 1 
/* These are all correct and will work */

this.setState({ a : this.state.a + 1 });
this.setState({ a : this.state.a + 1, b: this.state.b });
this.setState({ b: 5 });

Components changing the world

If you rememeber I mentioned previously that data only flows downwards in react. State information can be passed from a component down to it’s child components throught their properties. And if the children have children then it can continue to be passed down.

Nothing flows upwards. If a child component changes data that it got from it’s properties or in it’s state then it’s parent component does not know about it and nothing inside the parent changes.

But, I want to change the world

To change the world a component needs to be able to send data out. For example when a button inside a component is clicked it might want to change the background color or the whole app or something like that. To achieve this components use Events

React Events sidetrack

All browsers support a large number of events. Clicking, Scrolling, Resizing the window, Pressing a key, etc are a few of the many things that cause an event to be (fired). You can get access to these events by defining an event handler. An event handler is a function that is called when the event occurs.

Your funtion is also passed an Event object as it’s first argument. This event object contains data such as what causes the event to be fired, what kind of an event this is, etc.

In React things work exact the same as in the browser except for some small differences. React passes it’s own Synthetic Event object in place of the one the browser sends.

List of events in React

Example of a component using state and events

class VideoPlayer extends React.Component {
  constructor(props)  {
    super(props)
    this.state = { video: false }
  }

  playVideo = (e) => {
    this.setState({ video: true })
  }

  render() {
    if (this.state.video) {
      let src = `${this.props.video}?controls=0&autoplay=1`
      return (
        <Card>
          <iframe 
            width="800" 
            height="465" 
            src={src} 
            frameBorder="0" 
            allow="autoplay; encrypted-media" 
            allowFullScreen>
          </iframe>
        </Card>
      )
    }
    return (
      <Card>
        <img src={this.props.image} />
        <Center>
          <PlayButton size={250} onClick={this.playVideo} />
        </Center>
      </Card>
    )
  }
}

const profile = {
  image: 'https://www.youtube-nocookie.com/thumbnail/0sXvuUrJa0o.jpg',
  video: 'https://www.youtube-nocookie.com/embed/0sXvuUrJa0o'
}

const App = () => (
  <VideoPlayer video={profile.video} image={profile.image} />
)

ReactDOM.render(<App />, document.body);

And here’s the Video Player component, it uses everything you learnet above. When the comoponent starts at first video is set to false in the component state. We use the onClick event to trigger playVideo function which then sets video to true when the PlayButton icon is clicked.

The video field in the component state controls what to render inside the render() function of the component. If it’s true the Youtube video is rendered else the image with the play icon is.

...
<PlayButton size={250} onClick={this.playVideo} />
...

playVideo = (e) => {
  this.setState({ video: true })
}

The playVideo function might look strange to people familiar not familiar with the recent advances in Javascript (ES6). This is called an arrow funtion and it helps with how this works inside components. In short use it.

Keep in mind the on in onClick has to be lowercase while the rest title cased. React uses camel case for defining event handlers. That means the first letter of the first word is lowercase and the first letters of the next word is not. For example: onClick, onLoad, onToggle, onKeyDown

What now?

There is no secret ingredient. It’s just you.

― Po, Kung Fu Panda

Try this example

You must try this example it’s so worth it and the video embedded in the example is pretty cool too. You’ll have to run it on your own to find out :-)

$ git clone https://github.com/dosco/react-examples.git
$ cd react-examples/data-and-events
$ yarn install
$ yarn start --open

Follow me at twitter.com/dosco

  • Getting started with React

    Getting started with anything new is hard. In the frontend development world things are always changing, and changing fast. We’re gonna cut though all the complexity and get you Ninja status asap.

  • Data and React components

    The post second in this series on React. We focus on how data flows in and out of a React component and how you can use this data to connect multiple components together to build an app.

  • Building larger apps in React

    Having multiple pages in an app is pretty common. Take for example the Amazon app which has products and when you click one you get a detailed look at it. You’re gonna need to know how to build a React app with multiple pages so follow along.

  • Fetching Data in React

    Every React app needs to work with remote data. In this article we’ll walk though how you can make your React components talk to APIs and work with data.

  • Common Frontend Concepts

    React and the rest of the frontend development world is full of new terms. Anyone new can quickly feel overwhealmed. I’m going to try and explain the most popular terms that you will come across when working with React. Think of this as a glossary of things you will come across.