Getting Started With the React Javascript Library

If you spend any time in the WordPress world, you’ve probably come across Zac Gordon. Zac is an enthusiastic and charming teacher who focuses on Javascript in WordPress. He borrowed the phrase “Learn Javascript Deeply” from Matt Mullenweg and he made it into his personal slogan.

For the last several years, Zac has produced video classes, online conferences, live talks, and podcasts that focus on teaching you how to use Javascript in WordPress.

I’m delighted to say we’re working with Zac on a book, “React Explained“. React is the library the WordPress team have chose for the new Gutenberg editor. They are not alone – both Drupal and Magento have also chosen React.

Zac is live-tweeting his writing progress at @zgordon on Twitter. You can also hear Zac talk about React on the OSTraining podcast.

In this extract from the book, Zac gives you a high-level overview of React and some key concepts.


What is React?

Out of the box, React is a library for building user interfaces.

Although React is a JavaScript library, the interfaces that React builds are agnostic.

Several React companion libraries exist in order to make the interfaces you build work in the browser, on the server, in native applications and even in 360 and VR environments. In this book we focus on working with ReactDOM, the library that manages adding the interfaces we build with React to client side web sites and applications.  ReactDomServer, ReactNative and React360 are also libraries you may want to explore for using React interfaces in other environments.

In addition to providing helper functions for building interfaces, React’s architecture allows for you to handle interactions with your interfaces, whether that involves event handling, api calls, state management, updates to the interface, or more complex interactions.

React does not provide as many helper functions as some JavaScript frameworks. This is in large part why we call React a library and not a framework. You will still need to write plenty of vanilla JavaScript when working with React. 


React Component Architecture Explained

A component is an independent, reusable piece of code (created via a function or class).

React uses a component architecture for building user interfaces and organizing code. The main file for a simple React app may look something like this.

// Import React and Other Components import React from 'react'; import { render } from 'react-dom'; import Header from './Header'; import MainContent from './MainContent'; import Footer from './Footer';  function App(){   return (     <div className="app">       <Header />       <MainContent />       <Footer />     </div>  ); }  ReactDOM.render( <App />, document.getElementById("root"));

We can see here a few components in use. <Header />, <MainContent /> and <Footer /> are all components. The App() function is a component as well and we can see on the last line of this example how we can use the ReactDOM library and the ReactDOM.render() method to manage adding the UI we build to a webpage.

If we dig inside of the <Header />, <MainContent /> and <Footer /> components, we would likely see the use of more components as well as what looks like HTML markup.

import React from "react"; import Ad from "../Ad"; import logo from "../assets/logo.svg";  export default function Header() {   return (     <header className="app-header">       <Ad />       <img src={logo} className="app-logo" alt="logo" />       <h1 className="app-title">Site Name</h1>     </header>   ); }

In this <Header /> component above we can see that we are pulling in yet another component called <Ad />. Most React applications contain several layers of component nesting like we see with <App />, <Header /> and <Ad />.

We also see the use of HTML elements in our React code.  This is possible thanks to a library called JSX, which lets you write “HTML markup” directly in your JavaScript.  Since we are using React to create user interfaces, and user interfaces on the web involve HTML markup, this makes sense we would see HTML like elements within our UI components.  We will explore JSX in depth in this book.

If we look at some code from for a simple React app built using React 360, React’s VR library, the actual components we call would be different, but the component architecture is still present.

import React from 'react'; import {   Text,   View,   VrButton, } from 'react-360';  class Slideshow extends React.Component {   // Code removed for brevity   return (     <View style={styles.wrapper}>       <View style={styles.controls}>         <VrButton onClick={this.prevPhoto}>           <Text>{'Previous'}</Text>         </VrButton>         <VrButton onClick={this.nextPhoto}>          <Text>{'Next'}</Text>         </VrButton>       <View>         <Text style={styles.title}>{current.title}</Text>       </View>     </View>   ); }
 

The code above creates several layers of 360 views with some buttons and text overlaid. While the actual code might not make complete sense, it should be clear that we have several nested components representing view, buttons and text.

This is a good example because you can see how the same components are reused in different ways by passing them different parameters, or what React calls props.  Understanding how data passes through React components is important for understanding the typical component architecture used for building with React.


React Data Flow Explained

React follows a convention of getting and setting data at the highest point necessary in a component hierarchy for data to pass in a one way direction down through an application.Let’s take a look at this example and imagine some of the types of data we would need for various components.

function App() {   return(     <React.Fragment>       <Header />       <Content />       <Sidebar />       <Footer />     </React.Fragment>   ); }

Something like the name of the site might need to be available to both the <Header /> and <Footer />. The main content for the particular page would need to be passed to <Content />. Some additional widget data might need to go to <Sidebar />.

function App() {   const siteTitle = getSiteTitle();   const widgets = getWidgets();   const mainContent = getPageContent();   return(     <React.Fragment>       <Header siteTitle={siteTitle} />       <Content mainContent={mainContent} />       <Sidebar widgets={widgets} />       <Footer siteTitle={siteTitle} />     </React.Fragment>   ); }

This convention of making up attribute names and assigning them a value is how we pass data into a component.

Now the <Header /> and <Footer /> have access to the siteTitle, the <Content /> has access to the mainContent, and <Sidebar /> has access to the widgets it needs.

An important note is that this pattern of passing data into a component only passes the data one level. Components inside of <Header /> will not automatically get access to siteTitle.

function Header(props) {   return(     <header>       <p>We can see the {props.siteTitle} here.</p>       <PageHeader siteTitle={props.siteTitle} />       <PageSubHeader />     </header>   ); }

You can see here that inside <Header /> we can call props.siteTitle and have access to that value we passed into it. However, if we wanted to have access to siteTitle within the <PageHeader /> component we would have to manually pass that information down as well.

When a component receives a value as a prop, it should not modify it.  Props should pass through a component tree as immutable data.  This ensures that any component that references a prop, references the same value as it’s parent of children components.

The value of a prop should only be changed in the component that originally set the value of the prop and started passing it down through the component tree.  In our example code above, the <App /> component could change the value of siteTitle, but the <Header /> or <PageHeader /> components should not.

To understand the flow of how dynamic data gets updated in a React app involves discussion of state and how event handlers can be passed as props.


React Component States Explained

As we have learned, data flows down unchanged through components as props.  Data is set at the highest component in the tree necessary for all children components to be passed the information need as props.

In some cases, this data is received once and does not need to change.  In many cases though that data must remain dynamic and have the ability to update at any given time and have that update be reflected in all children components.

To keep track of data that changes in React we have a React state object and a set of helper functions to update the state value.

Here is an example of a counter that would update itself.  The value of the counter is a value that is dynamic within this component and therefore makes a good instance of when to rely on state.  Note that to make components with state, we must use JavaScript classes rather than functions.

class Counter extends Component {   state= {     counter:0   };    handleCount = () => {     this.setState({       counter: this.state.counter + 1     });   };    render() {     return (       <div>         <h1>{this.state.counter}</h1>         <button onClick={this.handleCount}>Count Up!!</button>       </div>     );   } }

Now it is important to note that this state is scoped to just this component.  The value of state in counter would not be available to child or parent components.

So in a more complex example example, like below, we would have to pass the value of counter down as a prop into the child element.

class Counter extends Component {   state= {     count:0   };    handleCount = () => {     this.setState({       count: this.state.count + 1     });   };    render() {     return (       <div>         <PageHeader count={this.state.count} />         <button onClick={this.handleCount}>Count Up!!</button>       </div>     );   } }

The <PageHeader /> count prop gets updated every time we update the state in the <Counter /> component

function PageHeader(props) {   return <h1>{props.count}</h1>;  }

The nice thing about this approach is that anytime state is updated, a new value will be automatically passed down into any child components with the value of a prop set to state.

This allows us to have a single point of truth for dynamic data.  The source of truth is the value in state, managed from a single component.  All instances of this value in children components are immutable values received as props that should not be changed outside of this component.

Components that appear above this component in the hierarchy would not have access to this data as it is only passed down via props.  We see again why we try to set and manage state from components higher in the hierarchy so that the data is available to everything that needs it.

There are some other architecture patterns, like higher order components and the context API, which circumvent needing to manually pass tons of props through your app.  We will explore these in more depth later.  For now we want to make sure we understand this high level overview of how things generally work before we start taking shortcuts.

Updating Component States in React

Now, what happens when we want to trigger state to be updated from a child component?

Imagine, for instance, that with the example above we wanted to have a <Button /> component rather than a hard coded button in our main <Counter /> component?  This is actually quite common in complex apps.

The solution to this, in the React world, is to pass the event handler function that updates the state with setState down as a prop.  Then it can be called from any child component, but the action will take place in the original component that set the state and has the ability to update it as well.  Other patterns for this exist, but this approach is the most basic.

If you are not familiar with passing functions as parameters, it is completely valid vanilla JavaScript.

Once state is updated, it will be passed down through the component hierarchy via the props.

Here is an example of what that would look like.

class Counter extends Component {   state= {     count:0   };    handleCount = () => {     this.setState({       count: this.state.count + 1     });   };    render() {     return (       <div>         <PageHeader count={this.state.count} />         <Button handleCount={this.handleCount} />               </div>     );   } }  function PageHeader( props ) {    return(      <h1>{props.count}</h1>  );  }  function Button( props ) {   return(     <button onClick={props.handleCount}>Count Up!!</button>     ); }

Here we can see a simple example of how React handles data flow.  There is a single point of truth for data.  That exists in state set and updated from a single component.  Data is passed in a one way flow down through a nested component tree via props.

If state needs to be updated from a component other than where it was originally set, then an event handler can be passed down to the necessary child component as a prop.  This keeps data immutable and flowing one way because even if a child component triggers a change, that change takes place higher up in the original component.

When we assign the value of a prop to something from state, like below, that prop value will automatically update whenever state changes.

<PageHeader counter={this.state.count} />

Any other child component that references that prop value will also receive the update automatically.  This is the beauty of data flow in React.

This can take a little while to get used to depending on how you have approached problems like these with JavaScript in the past.  However, this should all serve as a good starting point for us to be able to dig deeper into explaining React.

Author

  • Steve Burge

    Steve is the founder of OSTraining. Originally from the UK, he now lives in Sarasota in the USA. Steve's work straddles the line between teaching and web development.

0 0 votes
Article Rating
Subscribe
Notify of
1 Comment
Oldest
Newest
Inline Feedbacks
View all comments
Snehal Harshe
Snehal Harshe
2 years ago

Thank you so much for sharing all this wonderful information !!!! It is so appreciated!! You have good humor in your blogs. So much helpful and easy to read! You have wonderfully put all the details required for Java Coding with codes format. I would like to share this with my friends who are looking career in programming.

1
0
Would love your thoughts, please comment.x
()
x