Skip to content
This repository has been archived by the owner on May 26, 2021. It is now read-only.

An example WordPress theme with @wordpress/scripts and React.

Notifications You must be signed in to change notification settings

gregrickaby/example-wp-theme-with-react

Repository files navigation

Example WP Theme with React

Have you ever wanted to use a traditional WordPress theme, but add dynamic user interfaces to the front-end? Maybe there's an NPM package that you want to use, but you're not sure how to import and bundle it?

This repo is a proof of concept using @wordpress/scripts to bundle theme assets, use TailwindCSS for styles, and load the current weather conditions from the DarkSky API in the theme header.

Demo

First, we need to enqueue the styles, scripts, and their depdenencies e.g., React and ReactDom:

/* functions.php */

function example_scripts() {
	// Include the asset file generated by Webpack. This file includes dependencies!
	// https://developer.wordpress.org/block-editor/tutorials/javascript/js-build-setup/#dependency-management
	$asset_file = include 'build/index.asset.php';

	// Enqueue theme style.
	wp_enqueue_style( 'example-theme-style', get_stylesheet_directory_uri() . '/build/index.css', [], $asset_file['version'] );

	// Enqueue theme scripts.
	wp_enqueue_script( 'example-theme-script', get_stylesheet_directory_uri() . '/build/index.js', $asset_file['dependencies'], $asset_file['version'], true );
	wp_script_add_data( 'example-theme-script', 'async', true );
}
add_action( 'wp_enqueue_scripts', 'example_scripts' );

Next, fetch the current weather conditions in Los Angeles, CA from the DarkSky API. We'll sprinkle in some presentational classes from TailwindCSS. We also need to use ReactDom.render() to mount the <Weather /> component:

/* src/components/Header.js */

import React, { useState, useEffect } from "react";

// Use CORS anywhere to bypass CORS issues.
const CORS_PROXY = `https://cors-anywhere.herokuapp.com/`;

// Set weather API URL.
const WEATHER_API = `https://api.darksky.net/forecast/62627807ae3841ba587c80d49b90759b/37.8267,-122.4233`;

export default function Weather() {
  // Set initial state.
  const [loading, setLoading] = useState(true);
  const [weather, setWeather] = useState();

  // Fetch weather data.
  useEffect(() => {
    async function fetchData() {
      const response = await fetch(CORS_PROXY + WEATHER_API);
      const data = await response.json();
      setWeather(data);
      setLoading(false);
    }
    fetchData();
  }, []);

  // Display the <Weather /> component.
  return (
    <div className="text-right">
      {loading ? (
        <p>Getting weather info...</p>
      ) : typeof weather == "undefined" ? (
        <p>Unable to fetch results. Try reloading the page.</p>
      ) : (
        <>
          <p className="font-bold">Los Angeles, CA</p>
          <p className="text-sm">
            {weather.currently.summary} and{" "}
            {Math.round(weather.currently.temperature)}F
          </p>
          <p className="text-sm">{weather.daily.summary}</p>
        </>
      )}
    </div>
  );
}

// Mount <Weather /> component to <div id="weather">.
ReactDOM.render(<Weather />, document.getElementById("weather"));

Now it's time to setup TailwindCSS. Create a new file named, postcss.config.js:

module.exports = {
  plugins: [require("tailwindcss"), require("postcss-preset-env")],
};

PostCSS is what @wordpress/scripts will use to turn TailwindCSS into actual CSS.


If you want to use PurgeCSS to remove unused CSS, create a new file named tailwind.config.js:

module.exports = {
  purge: ["./src/components/*.js"], // This will purge unused CSS.
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
};

Now, bring in the directives from TailwindCSS and basic CSS for demo purposes:

/* src/index.scss */

@tailwind base;
@tailwind components;
@tailwind utilities;

/* BASIC GRID STYLE FOR DEMO PURPOSES. */
#site-header,
#site-content,
#site-footer {
  margin: 0 auto 24px;
  max-width: 740px;
}

We're almost there! We need to import both the Sass file and <Weather /> component in our entry file.

/* src/index.js */

import "./index.scss";
import Weather from "./components/Weather";

The entry file is required so that @wordpress/scripts knows what to build.


Finally, tell @wordpress/scripts to build and bundle everything up!

npm run build

The result:

screenshot


What just happened?

In functions.php we're enqueueing our bundled JavaScript and CSS file and requiring wp-element as a depdendency, which includes both React and ReactDom. These files will be loaded on the front-end!

Try out this demo

Clone down the repo into wp-content/themes and install the dependencies:

git@github.com:gregrickaby/example-wp-theme-with-react.git
cd themes/example-wp-theme-with-react
npm install

Activate the theme in WordPress.

Development

To start HMR:

npm run start

To lint scripts and styles:

npm run lint

To build production ready assets:

npm run build