React JS part II

27th Jul 18
amsterdam at night

In this blog I go through how to define a class based component and a functional component. I cover how to pass props (or attributes) down to a child component and in doing so making the component more dynamic.  I also go through adding a state to a class based component and how to update the state through event handlers.

Defining a component

React is all about making components.  Typically you render one root component in the index.js file within the src folder.  And in that root component you would nest all the other components you need to build you application.  If you look at the below example:

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
      <h1>Hi I am learning React JS</h1>
      </div>
    );
  }
}

export default App;

To define a component, you firstly create a class that extends a Component to inherit the methods.  This component class comes from the React library and is imported at the top of the file.  The method that should be called within the class is the render method.  React calls this render method to call the render it to the browser.  Within the render function is has to return some JSX code that can be rendered to the DOM.  We then export the class.

Understanding JSX

Another way to write the return statement is a such: 

 return React.createElement(
      'div',{className:'App'},React.createElement(
                              'h1',null, 'Hi I am learning React JS!!!'
                              )
      );

It is exactly the same as the previous JSX code.  Therefore you need to import React so that the code is compiled using createElement method even though you don't state React.createElement in the previous example.

Create A Functional Component

In a seperate file I create a Person.js within a Person folder.  I include a function returning some JSX and export the function making sure I import React from the React library.

import React from 'react';

const person  = () => {
    return(
        <p>I'm a person</p>
    )
};

export default person;

Then in my root component file I import the person.js file as 'Person' at the top of the file.  Note that the name you assign it should be capitalised. This is because in React all the lowercase tags are reserved for the native HTML tags where as any capitalised tag names are seen as React Components.

import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person';

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hi I am learning React JS</h1>
        <Person />
      </div>
    );

  }
}

export default App;

 

Outputting some dynamic content

To pass any javascript from within the JSX code, we have to wrap it in { }.  In the below example I output a random number: 

const person  = () => {
    return(
        <p>I'm a person and I am {Math.floor(Math.random()*30)} years old!</p>
    )
};

The output on the browser is seen as 'I'm a person and I am 7 years old!', with a different number generated on refresh of the browser.

 

Using Props

You can pass down attributes to your child component and React gives us access to the attributes on an object called 'props'.  Thus the functional component can receive one argument  ('props') that can receive all the attributes passed to it as properties of that object.  Take my example below. I have three people and I pass their name and age to the person component.

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hi I am learning React JS</h1>
        <Person name="Annelies" age="46"/>
        <Person name="Christina" age="40"/>
        <Person name="Jan Paul" age="44"/>
      </div>
    );
  }
}

  I accept the props as an argument to its functional component which holds the attributes in key value pairs. 

const person  = (props) => {
    return(
        <p>I'm a {props.name} and I am {props.age} years old!</p>
    )
};

So I am able to make my component dynamic by passing down attributes to it. 

screenshot of rendered React Js code
My App component with person child components rendered to the browser

Passing Content to the Child Component

You can pass content to the component through the children property of the props object.  

// in the App.js
 return (
      <div className="App">
        <h1>Hi I am learning React JS</h1>
        <Person name="Annelies" age="46">My Hobbies: Crochet and Knitting</Person>
        <Person name="Christina" age="40">My Hobbies: Gardening</Person>
        <Person name="Jan Paul" age="44">My Hobbies: Golf</Person>
      </div>
    );

// in Person.js
return(
        <div>
             <p>I'm a {props.name} and I am {props.age} years old!</p>
             <p>{props.children}</p>
        </div> 
        )

Note that every component should be wrapped in a root div.

screenshot of rendered React JS code
Output of React JS code

 

State

Within a React class based component that extends the Component class, such as the App component I created previously, you can define a special property name: state.  On a side note you should use functional components (or stateless) as much as possible, such as the Person component, as having multiple stateful components makes that application complicated and difficult to manage.  

In my App class based component I add a state property, which is an object and a persons array.  Within that array I have a list of objects containing the names and ages of my people. My example below will result in the exact same output but using the state property.

class App extends Component {
  state = {
    persons: [
      {name: 'Christina', age: 40},
      {name: 'Jan Paul', age: 44},
      {name: 'Annelies', age: 46}
    ]
  };
  render() {
    return (
      <div className="App">
        <h1>Hi I am learning React JS</h1>
        <button onClick={}>Switch Name</button>
        <Person name={this.state.persons[0].name} 
                age={this.state.persons[0].age}>My Hobbies: Crochet and Knitting
        </Person>
        <Person name={this.state.persons[1].name} 
                age={this.state.persons[1].age}>My Hobbies: Gardening
        </Person>
        <Person name={this.state.persons[2].name} 
                 age={this.state.persons[2].age}>My Hobbies: Golf
        </Person>
      </div>
    );
  }
}

The special characteristic of state is that when the values within the state property changes, React will re-render to the DOM and the updated data will be automatically updated.

Event Listeners

In my button I add an event handler, onClick.  This will run a function when the button is clicked.  I create that named function within the class component.  Note that when I refer to the function in the event handler I refer to 'this'.  'This' key word refers to the object generated from the class component 'App'.  Accessing any property of the class such as the state or a function (method) you need to use the key word 'this'.  Also note that I don't add the parenthesis to the function, so to prevent it from being called when the component is renders as we want to call the function when the button is clicked.  Currently I just write a comment to the console: 

  switchNameHandler = () => {
console.log('Was Clicked');
  }

// and the button with the event handler

   <button onClick={this.switchNameHandler}>Switch Name</button>

A list of supported events are listed here.

Manipulating the state

To change the state you should not alter it directly but use a React method setState.  SetState takes an object as an argument and will merge whatever gets passed to that object with the existing state object.  React will then look at the state as see what part we are overriding and alter accordingly.  

  switchNameHandler = () => {
    this.setState({
      persons:[
        {name: 'Teenie', age: 40},
        {name: 'Jan Paul', age: 44},
       {name: 'Annelies', age: 46}
      ]
    });
  }

So when I click on the button now, I will change 'Christina' to 'Teenie'. 

I have recently completed my apprenticeship.  I am currently building the API to a React JS site using Firebase.