如何使用WooCommerce在React.js主题中呈现WP REST-API端点

时间:2019-02-06 作者:Tony Wheeler

我正在使用React构建一个电子商务Wordpress/Woocommerce主题。js。我正在使用npm软件包:

create-react-wptheme

此包直接在索引内部呈现react应用程序。wordpress主题的php。

我不确定如何访问react中的wordpress api端点。js组件。我已经使用jsx为站点创建了模板,需要访问api端点来呈现动态内容。我可以使用对外部api的http请求访问这些点,但我需要能够访问react wp主题内的完整api。

据我所知,我需要使用主干。js api客户端使用react访问wp rest api。

或者我可能需要一个npm包来连接这个。

如何使api在我的应用程序中可用。js和组件?

我想发出一个基本的GET请求来获取posts对象,但我不知道如何将wp Rest API导入react。

这是一个帖子页面,我正在那里试图获取帖子。它带来了一个错误。页面如下:

    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;
此处不显示此页面,这是来自控制台的错误。

    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)
这是我的功能。我创建用来访问api的php。

<?php

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

?>
这是我的索引。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.com/icon?family=Material+Icons"
      rel="stylesheet"
    />
    <!-- Font Awesome -->
    <link
      rel="stylesheet"
      href="https://use.fontawesome.com/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>
这是我的应用程序。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;
这是我的索引。将根指向我的应用程序的js。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"));

1 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

我可以使用对外部api的http请求访问这些点,但我需要能够访问react wp主题内的完整api。

您可以使用wp-api script / Backbone JavaScript client library 或其他客户端库之一listed here 例如node-wpapi library.

使用wp-api 脚本将脚本排入队列:

wp_enqueue_script( \'wp-api\' );
  • 英寸index.php, 确保<?php wp_head(); ?> 已添加到文档中head, 和<?php wp_footer(); ?>body.

    然后在React组件中,通过访问客户端window.wp.api 而不仅仅是wp.api:

    const postsCollection = new window.wp.api.collections.Posts(); // like this
    //const postsCollection = new wp.api.collections.Posts();      // not this
    
    下面是一个示例React组件,它使用Posts 集合检索一篇文章:(标记基于Post 组件)

    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;
    
    经过测试,工作正常,代码基于the official example.

    使用node-wpapi

    您可以参考documentation 在…上installing the libraryusing it.

    但以上是Post 组件,适用于使用node-wpapi 图书馆:(the... 表示未更改)

    import React from "react";
    
    const WPAPI = require(\'wpapi\');
    const wp = new WPAPI({
      endpoint: \'http://example.com/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;
    
    完整代码可以查看我的文件here.

  • 相关推荐

    JavaScript in a PHP plugin

    我正在编写一个插件(在PHP中),它输出array.生成的数组应该是某个JavaScript文件的输入,该文件根据数组输出图表(.png图像)。考虑到这一点,我应该将变量从PHP插件传递给JavaScript(如图所示here).我想知道使用插件的过程是否与普通PHP文件不同。。。JS图表应根据用户操作显示。简而言之:如何调用JS文件,通过普通插件向其传递变量?