React in WordPress

What is React?

Data => Rectangles

Why use React?

What's wrong with just outputting HTML?

It's about experience

Yeah but I love jQuery

or

Just use Vanilla

When to use React

  • High Degree of interactivity
  • Same Data appearing in multiple places
  • When instant validation and feedback is helpful

When not to use React

  • If you are just displaying static information
  • If you only need to affect a few elements

Single Page Applications?

What about Vue?

or Angular?

or Mithril?

or Preact?

or Ember?

or Polymer?

or Knockout?

Let's take a look

function no_js_store() {

    $products = array();

    $query = new WP_Query( $query_args );
    if ( $query->have_posts() ) {
      while ( $query->have_posts() ) {

         $name = get_the_title();

         $products[] = array(
           "name" => $name,
        );
      }
    }
    
    foreach ($products as $product) {
      $products_html .= return_product_html($product);
    }

  	return $products_html;

  }

add_shortcode( 'no-js-store', 'no_js_store' );

Let's take a look

function react_store() {
    wp_enqueue_script( 'react-wp-demo-js' );
    $products = array();

    $query = new WP_Query( $query_args );
    if ( $query->have_posts() ) {
      while ( $query->have_posts() ) {

         $name = get_the_title();

         $products[] = array(
           "name" => $name,
        );
      }
    }

    $data_for_store_js = '{products:'.json_encode($products).'}';

    $products_html .= '<script>var storeData = '.$data_for_store_js.';</script><section id="store-root"></section>';

  	return $products_html;

  }
  add_shortcode( 'react-store', 'react_store' );

Two Types of Components

Functional and Class

Functional (Stateless)

function Product(props) {
  return (
    <fieldset className={"product " + 
    (props.price <= props.moneyRemaining ? "affordable" : "unaffordable")
    }>
    <label className="product-label">
      <h3 className="product-title">{props.name}</h3>
      <p className="product-price">
        <span className="product-price-symbol">$</span>
        {props.price}
      </p>
      <p className="product-content">{props.content}</p>
      <p className="product-category">{props.categories}</p>
    </label>
    <ProductCounter id={props.id} count={props.count} 
        setCount={props.setCount} minusCount={props.minusCount} 
        addCount={props.addCount} />
    </fieldset>
  );
}
function return_product_html($product) {
  $output =
  '<fieldset class="product">
  <label class="product-label">
    <h3 class="product-title">' . $product['name'] . '</h3>
    <p class="product-price">
        <span class="product-price-symbol">$</span>
        ' . $product['price'] . '
    </p>
    <p class="product-content">' . $product['content'] . '</p>
    <p class="product-category">' . $product['categories'] . '</p>
  </label>
  <input class="product-count" type="number" value=0>
  </fieldset>';
  return $output;
}

Class Components

class Store extends React.Component {
	constructor(props) {
		super(props);
		this.state = storeData;
	}

	addCount(product) {
		let newState = this.state;
		if (this.state.moneyRemaining >= newState.products[product].price) {
			newState.products[product].count++;
		}
		this.setState({newState});
		this.calculateRemaining();
	}

	render() {
		return (
			<div id="store-wrapper">
				// Components here
			</div>
	);}}

But how do we affect the State from down the tree?

render() {
    return (
	<div id="store-wrapper">
         <h3>You Have: ${this.state.moneyRemaining}</h3>
	 <form className="store" method="post">
	   { this.state.products.map((product, i) => {
             return (<Product key={i} id={i}
                     moneyRemaining={this.state.moneyRemaining} 
                     name={product.name}
                     setCount={this.setCount.bind(this)} />);
	    })}
	 </form>
         <h3>Estimated Bill:
            ${this.state.money - this.state.moneyRemaining}
         </h3>
         <button className="checkout">Check Out</button>
	</div>
    );
}
class ProductCounter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {count: this.props.count};
        this.handleAdd = this.handleAdd.bind(this);
    }
    handleAdd(e) {
        e.preventDefault();
	this.props.addCount(this.props.id);
    }
    render() {
        return (
	    <div className="product-counter">
	        <button className="product-count-button"
                onClick={this.handleAdd}>+</button>
	    </div>
	);
    }
}

Build Steps?

Babel!

{
  "name": "react-wp-demo",
  "version": "0.0.1",
  "description": "Demo of React in WordPress",
  "main": "react-wp-demo.php",
  "scripts": {
    "babel": "babel",
    "build": "babel js/src -d js",
    "style": "sass --update styles"
  },
  "repository": {
    "type": "git",
    "url": "https://github.ncsu.edu/oitdesign/react-wp-demo.git"
  },
  "author": "Miles Elliott, OIT Design",
  "devDependencies": {
    "babel-cli": "^6.23.0",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-react": "^6.23.0",
    "babel-preset-stage-0": "^6.22.0",
    "eslint": "^3.15.0",
    "eslint-config-google": "^0.7.1",
    "eslint-plugin-react": "^6.9.0"
  }
}
{
  "presets": [
    "es2015",
    "react"
  ]
}

What You Get

Nothing that was impossible

Support Concerns

  • Only supports IE9+

  • You need to have a fallback if JavaScript is disabled
  • Some Search Engines won't detect it (Google will now)
  • The action is taking place on the client's device, so you are subject to potential bottlenecks there

Getting Started

Don't start with React in WordPress

Get down the React part first

 

facebook.github.io/react/docs/hello-world.html

Create React App

React in WordPress

By milesdelliott

React in WordPress

  • 42