$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>javascript - How to render WP Rest-API Endpoints in a React.js Theme with Woocommerce|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - How to render WP Rest-API Endpoints in a React.js Theme with Woocommerce

matteradmin9PV0评论

I am building a Ecommerce Wordpress/Woocommerce Theme using React.js. I am using the npm package:

create-react-wptheme

This package renders the react app directly inside of the index.php of the wordpress theme.

I am unsure how to access the wordpress api endpoints inside of react.js components. I have created the templates for the site using jsx, and need to access the api Endpoints to render dynamic content. I can access the points using http requests to the external api, but I need to be able to access the full api inside of the react-wp-theme.

From what I understand I need to use the backbone.js api client to access the wp rest-api using react.

Or do i possibly need a npm package to hook this up.

How can I make the api available inside of my app.js and components?

I want to make a basic GET request to fetch the posts object, but I do not know how to import the wp Rest-API into react.

Here is a post page where I am trying to fetch a post. It brings up an error. Here is the page:

    import React from "react";


    class Post extends React.Component {
      render() {
        let wpPosts = new window.wp.api.collections.Posts();
wpPosts.fetch({ data: { per_page: 2 } }).done(posts => {
          posts.forEach(post => {
            console.log(post.title.rendered);
        });
        return (
          <div className="container indigo lighten-4">
            <div className="container flow-text py-5 mt-5">
              <h1>Title</h1>
              <p>
                content
              </p>
            </div>
          </div>
        );
      }
    }

    export default Post;

This Page Does not display here is the error from the console.

    Post.js:6 Uncaught TypeError: Cannot read property 'api' of undefined
    at Post.render (Post.js:6)
    at finishClassComponent (react-dom.development.js:15141)
    at updateClassComponent (react-dom.development.js:15096)
    at beginWork (react-dom.development.js:15980)
    at performUnitOfWork (react-dom.development.js:19102)
    at workLoop (react-dom.development.js:19143)
    at HTMLUnknownElement.callCallback (react-dom.development.js:147)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:196)
    at invokeGuardedCallback (react-dom.development.js:250)
    at replayUnitOfWork (react-dom.development.js:18350)
render @ Post.js:6
finishClassComponent @ react-dom.development.js:15141
updateClassComponent @ react-dom.development.js:15096
beginWork @ react-dom.development.js:15980
performUnitOfWork @ react-dom.development.js:19102
workLoop @ react-dom.development.js:19143
callCallback @ react-dom.development.js:147
invokeGuardedCallbackDev @ react-dom.development.js:196
invokeGuardedCallback @ react-dom.development.js:250
replayUnitOfWork @ react-dom.development.js:18350
renderRoot @ react-dom.development.js:19261
performWorkOnRoot @ react-dom.development.js:20165
performWork @ react-dom.development.js:20075
performSyncWork @ react-dom.development.js:20049
requestWork @ react-dom.development.js:19904
scheduleWork @ react-dom.development.js:19711
scheduleRootUpdate @ react-dom.development.js:20415
updateContainerAtExpirationTime @ react-dom.development.js:20441
updateContainer @ react-dom.development.js:20509
push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @ react-dom.development.js:20820
(anonymous) @ react-dom.development.js:20974
unbatchedUpdates @ react-dom.development.js:20292
legacyRenderSubtreeIntoContainer @ react-dom.development.js:20970
render @ react-dom.development.js:21037
./src/index.js @ index.js:6
__webpack_require__ @ bootstrap:78
0 @ serviceWorker.js:135
__webpack_require__ @ bootstrap:78
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
react-dom.development.js:16764 The above error occurred in the <Post> component:
    in Post (created by Route)
    in Route (at Routes.js:29)
    in Switch (at Routes.js:20)
    in Routes (at App.js:18)
    in div (at App.js:16)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:15)
    in App (at src/index.js:6)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit  to learn more about error boundaries.
logCapturedError @ react-dom.development.js:16764
logError @ react-dom.development.js:16800
update.callback @ react-dom.development.js:17814
callCallback @ react-dom.development.js:11743
commitUpdateEffects @ react-dom.development.js:11783
commitUpdateQueue @ react-dom.development.js:11773
commitLifeCycles @ react-dom.development.js:17055
commitAllLifeCycles @ react-dom.development.js:18512
callCallback @ react-dom.development.js:147
invokeGuardedCallbackDev @ react-dom.development.js:196
invokeGuardedCallback @ react-dom.development.js:250
commitRoot @ react-dom.development.js:18717
completeRoot @ react-dom.development.js:20247
performWorkOnRoot @ react-dom.development.js:20170
performWork @ react-dom.development.js:20075
performSyncWork @ react-dom.development.js:20049
requestWork @ react-dom.development.js:19904
scheduleWork @ react-dom.development.js:19711
scheduleRootUpdate @ react-dom.development.js:20415
updateContainerAtExpirationTime @ react-dom.development.js:20441
updateContainer @ react-dom.development.js:20509
push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @ react-dom.development.js:20820
(anonymous) @ react-dom.development.js:20974
unbatchedUpdates @ react-dom.development.js:20292
legacyRenderSubtreeIntoContainer @ react-dom.development.js:20970
render @ react-dom.development.js:21037
./src/index.js @ index.js:6
__webpack_require__ @ bootstrap:78
0 @ serviceWorker.js:135
__webpack_require__ @ bootstrap:78
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
react-dom.development.js:20135 Uncaught TypeError: Cannot read property 'api' of undefined
    at Post.render (Post.js:6)
    at finishClassComponent (react-dom.development.js:15141)
    at updateClassComponent (react-dom.development.js:15096)
    at beginWork (react-dom.development.js:15980)
    at performUnitOfWork (react-dom.development.js:19102)
    at workLoop (react-dom.development.js:19143)
    at renderRoot (react-dom.development.js:19228)
    at performWorkOnRoot (react-dom.development.js:20165)
    at performWork (react-dom.development.js:20075)
    at performSyncWork (react-dom.development.js:20049)

Here is my functions.php that I created to access the api.

<?php

function my_theme_scripts() {
  // Enqueue the Backbone JavaScript Client.
  wp_enqueue_script( 'wp-api' );
}
add_action( 'wp_enqueue_scripts', 'my_theme_scripts' );

?>

Here is My index.php

<?php
  $TEMPLATE_PATH = parse_url(get_template_directory_uri(), PHP_URL_PATH);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
        <!-- Material Icons -->
        <link
      href="+Icons"
      rel="stylesheet"
    />
    <!-- Font Awesome -->
    <link
      rel="stylesheet"
      href=".6.3/css/all.css"
      integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
      crossorigin="anonymous"
    />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="<?php echo $TEMPLATE_PATH; ?>/manifest.json">
    <?php wp_head(); ?> 

    <title>React WordPress Theme</title>
</head>
    <body>
    <noscript>
        You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>

    </body>
    <?php wp_footer(); ?>
</html>

Here is my App.js

import React, { Component } from "react";
import "./scss/App.scss";
import "./scss/pbml.scss";
import Headers from "./routers/Headers";
import Footer from "./components/footer/Footer";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

import "materialize-css/dist/css/materialize.min.css";

import Routes from "./routers/Routes";

class App extends Component {
  render() {
    return (
      <Router>
        <div className="cosmos">
          <Headers />
          <Routes />
          <Footer />
        </div>
      </Router>
    );
  }
}

export default App;

And Here is my index.js that just points the root to my app.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

ReactDOM.render(<App />, document.getElementById("root"));

I am building a Ecommerce Wordpress/Woocommerce Theme using React.js. I am using the npm package:

create-react-wptheme

This package renders the react app directly inside of the index.php of the wordpress theme.

I am unsure how to access the wordpress api endpoints inside of react.js components. I have created the templates for the site using jsx, and need to access the api Endpoints to render dynamic content. I can access the points using http requests to the external api, but I need to be able to access the full api inside of the react-wp-theme.

From what I understand I need to use the backbone.js api client to access the wp rest-api using react.

Or do i possibly need a npm package to hook this up.

How can I make the api available inside of my app.js and components?

I want to make a basic GET request to fetch the posts object, but I do not know how to import the wp Rest-API into react.

Here is a post page where I am trying to fetch a post. It brings up an error. Here is the page:

    import React from "react";


    class Post extends React.Component {
      render() {
        let wpPosts = new window.wp.api.collections.Posts();
wpPosts.fetch({ data: { per_page: 2 } }).done(posts => {
          posts.forEach(post => {
            console.log(post.title.rendered);
        });
        return (
          <div className="container indigo lighten-4">
            <div className="container flow-text py-5 mt-5">
              <h1>Title</h1>
              <p>
                content
              </p>
            </div>
          </div>
        );
      }
    }

    export default Post;

This Page Does not display here is the error from the console.

    Post.js:6 Uncaught TypeError: Cannot read property 'api' of undefined
    at Post.render (Post.js:6)
    at finishClassComponent (react-dom.development.js:15141)
    at updateClassComponent (react-dom.development.js:15096)
    at beginWork (react-dom.development.js:15980)
    at performUnitOfWork (react-dom.development.js:19102)
    at workLoop (react-dom.development.js:19143)
    at HTMLUnknownElement.callCallback (react-dom.development.js:147)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:196)
    at invokeGuardedCallback (react-dom.development.js:250)
    at replayUnitOfWork (react-dom.development.js:18350)
render @ Post.js:6
finishClassComponent @ react-dom.development.js:15141
updateClassComponent @ react-dom.development.js:15096
beginWork @ react-dom.development.js:15980
performUnitOfWork @ react-dom.development.js:19102
workLoop @ react-dom.development.js:19143
callCallback @ react-dom.development.js:147
invokeGuardedCallbackDev @ react-dom.development.js:196
invokeGuardedCallback @ react-dom.development.js:250
replayUnitOfWork @ react-dom.development.js:18350
renderRoot @ react-dom.development.js:19261
performWorkOnRoot @ react-dom.development.js:20165
performWork @ react-dom.development.js:20075
performSyncWork @ react-dom.development.js:20049
requestWork @ react-dom.development.js:19904
scheduleWork @ react-dom.development.js:19711
scheduleRootUpdate @ react-dom.development.js:20415
updateContainerAtExpirationTime @ react-dom.development.js:20441
updateContainer @ react-dom.development.js:20509
push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @ react-dom.development.js:20820
(anonymous) @ react-dom.development.js:20974
unbatchedUpdates @ react-dom.development.js:20292
legacyRenderSubtreeIntoContainer @ react-dom.development.js:20970
render @ react-dom.development.js:21037
./src/index.js @ index.js:6
__webpack_require__ @ bootstrap:78
0 @ serviceWorker.js:135
__webpack_require__ @ bootstrap:78
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
react-dom.development.js:16764 The above error occurred in the <Post> component:
    in Post (created by Route)
    in Route (at Routes.js:29)
    in Switch (at Routes.js:20)
    in Routes (at App.js:18)
    in div (at App.js:16)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:15)
    in App (at src/index.js:6)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
logCapturedError @ react-dom.development.js:16764
logError @ react-dom.development.js:16800
update.callback @ react-dom.development.js:17814
callCallback @ react-dom.development.js:11743
commitUpdateEffects @ react-dom.development.js:11783
commitUpdateQueue @ react-dom.development.js:11773
commitLifeCycles @ react-dom.development.js:17055
commitAllLifeCycles @ react-dom.development.js:18512
callCallback @ react-dom.development.js:147
invokeGuardedCallbackDev @ react-dom.development.js:196
invokeGuardedCallback @ react-dom.development.js:250
commitRoot @ react-dom.development.js:18717
completeRoot @ react-dom.development.js:20247
performWorkOnRoot @ react-dom.development.js:20170
performWork @ react-dom.development.js:20075
performSyncWork @ react-dom.development.js:20049
requestWork @ react-dom.development.js:19904
scheduleWork @ react-dom.development.js:19711
scheduleRootUpdate @ react-dom.development.js:20415
updateContainerAtExpirationTime @ react-dom.development.js:20441
updateContainer @ react-dom.development.js:20509
push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @ react-dom.development.js:20820
(anonymous) @ react-dom.development.js:20974
unbatchedUpdates @ react-dom.development.js:20292
legacyRenderSubtreeIntoContainer @ react-dom.development.js:20970
render @ react-dom.development.js:21037
./src/index.js @ index.js:6
__webpack_require__ @ bootstrap:78
0 @ serviceWorker.js:135
__webpack_require__ @ bootstrap:78
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
react-dom.development.js:20135 Uncaught TypeError: Cannot read property 'api' of undefined
    at Post.render (Post.js:6)
    at finishClassComponent (react-dom.development.js:15141)
    at updateClassComponent (react-dom.development.js:15096)
    at beginWork (react-dom.development.js:15980)
    at performUnitOfWork (react-dom.development.js:19102)
    at workLoop (react-dom.development.js:19143)
    at renderRoot (react-dom.development.js:19228)
    at performWorkOnRoot (react-dom.development.js:20165)
    at performWork (react-dom.development.js:20075)
    at performSyncWork (react-dom.development.js:20049)

Here is my functions.php that I created to access the api.

<?php

function my_theme_scripts() {
  // Enqueue the Backbone JavaScript Client.
  wp_enqueue_script( 'wp-api' );
}
add_action( 'wp_enqueue_scripts', 'my_theme_scripts' );

?>

Here is My index.php

<?php
  $TEMPLATE_PATH = parse_url(get_template_directory_uri(), PHP_URL_PATH);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
        <!-- Material Icons -->
        <link
      href="https://fonts.googleapis/icon?family=Material+Icons"
      rel="stylesheet"
    />
    <!-- Font Awesome -->
    <link
      rel="stylesheet"
      href="https://use.fontawesome/releases/v5.6.3/css/all.css"
      integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
      crossorigin="anonymous"
    />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="<?php echo $TEMPLATE_PATH; ?>/manifest.json">
    <?php wp_head(); ?> 

    <title>React WordPress Theme</title>
</head>
    <body>
    <noscript>
        You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>

    </body>
    <?php wp_footer(); ?>
</html>

Here is my App.js

import React, { Component } from "react";
import "./scss/App.scss";
import "./scss/pbml.scss";
import Headers from "./routers/Headers";
import Footer from "./components/footer/Footer";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

import "materialize-css/dist/css/materialize.min.css";

import Routes from "./routers/Routes";

class App extends Component {
  render() {
    return (
      <Router>
        <div className="cosmos">
          <Headers />
          <Routes />
          <Footer />
        </div>
      </Router>
    );
  }
}

export default App;

And Here is my index.js that just points the root to my app.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

ReactDOM.render(<App />, document.getElementById("root"));
Share Improve this question edited Feb 7, 2019 at 5:25 Toni Wheeler asked Feb 6, 2019 at 1:22 Toni WheelerToni Wheeler 33 bronze badges 10
  • This might help. – Sally CJ Commented Feb 6, 2019 at 1:42
  • I have read the documentation, but I am having difficulty importing the rest-api into my react components. I updated the question to include more info. – Toni Wheeler Commented Feb 6, 2019 at 3:38
  • You enqueue scripts on the front-end using the wp_enqueue_scripts hook - e.g. In functions.php, do add_action( 'wp_enqueue_scripts', function(){ wp_enqueue_script( 'wp-api' ); } ). – Sally CJ Commented Feb 6, 2019 at 3:49
  • But, you don't have wp_head(); in your template (index.php), so you could put it there - before </head>, or try adding wp_print_scripts( 'wp-api' ); before </body>.. – Sally CJ Commented Feb 6, 2019 at 4:04
  • Thanks for your help. I have expanded the project to include a functions.php, and added the wp_head and wp_footer to my index.php. I still have the same error, because Im not sure how to access the wp-api in react. What do I call in the js file to import wp? – Toni Wheeler Commented Feb 6, 2019 at 6:40
 |  Show 5 more comments

1 Answer 1

Reset to default 1

I can access the points using http requests to the external api, but I need to be able to access the full api inside of the react-wp-theme.

You could use either the wp-api script / Backbone JavaScript client library or one of the other client libraries listed here such as the node-wpapi library.

Using the wp-api script

  1. Enqueue the script:

    wp_enqueue_script( 'wp-api' );
    
  2. In index.php, make sure <?php wp_head(); ?> is added in the document head, and <?php wp_footer(); ?> in the body.

And then in your React components, access the client via window.wp.api instead of just wp.api:

const postsCollection = new window.wp.api.collections.Posts(); // like this
//const postsCollection = new wp.api.collections.Posts();      // not this

Here's an example React Component which uses the Posts collection to retrieve one post: (the markup is based on your Post component)

import React from "react";

class Post extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      item: {}
    };
  }

  componentDidMount() {
    // Instantiates the collection.
    const postsCollection = new window.wp.api.collections.Posts();

    // Retrieves one post.
    postsCollection.fetch({ data: { per_page: 1 } })
      .done(posts => {
        this.setState({
          isLoaded: true,
          item: posts[0]
        });
      })
      .error((xhr, status, error) => {
        this.setState({
          isLoaded: true,
          error
        });
      });
  }

  render() {
    const { error, isLoaded, item } = this.state;
    if (error || item.errors) {
      return <div>Error: {error || 'API error...'}</div>;
    } else if (! isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <div className="container indigo lighten-4">
          <div className="container flow-text py-5 mt-5">
            <h3>{item.title.rendered}</h3>
            <p>{item.excerpt.rendered}</p>
          </div>
        </div>
      );
    }
  }
}

export default Post;

Tried and tested working, and the code is based on the official example.

Using the node-wpapi library

You can refer to the documentation on installing the library and using it.

But here's the above Post component, adapted to using the node-wpapi library: (the ... means nothing changed)

import React from "react";

const WPAPI = require('wpapi');
const wp = new WPAPI({
  endpoint: 'http://example/wp-json'
});

class Post extends React.Component {
  constructor(props) {
    ...
  }

  componentDidMount() {
    // Retrieves one post.
    wp.posts().perPage(1)
      .then(posts => {
        this.setState({
          isLoaded: true,
          item: posts[0]
        });
      })
      .catch(err => {
        this.setState({
          isLoaded: true,
          error: err.message
        });
      });
  }

  render() {
    ...
  }
}

export default Post;

The Full Code

You can check my files here.

Post a comment

comment list (0)

  1. No comments so far