I’m using React to build the front-end of a site which uses WordPress for the back-end. In particular, I’m using the WordPress REST API to pull in and display content.

By default, the WordPress REST API doesn’t expose menu information, so I’ve extended it to include it:

function get_menu( $data ) {
  return wp_get_nav_menu_items( $data[ 'slug' ] );
}

add_action( 'rest_api_init', function () {

  register_rest_route( 'custom', '/menus/(?P<slug>[a-zA-Z0-9-]+)', 
    array(
      'methods'  => 'GET',
      'callback' => 'get_menu'
    )
  );

});

Now I can access my menu information with a request like the following:

http://localhost:8888/learn-react/admin/wp-json/custom/menus/main-menu

The response I get for each of the items included in the menu looks like this:

ID: 13
attr_title: ""
classes: [""]
comment_count: "0"
comment_status: "closed"
db_id: 13
description: ""
filter: "raw"
guid: "http://localhost:8888/learn-react/admin/?p=13"
menu_item_parent: "0"
menu_order: 3
object: "page"
object_id: "8"
ping_status: "closed"
pinged: ""
post_author: "1"
post_content: " "
post_content_filtered: ""
post_date: "2018-02-10 08:57:52"
post_date_gmt: "2018-02-10 08:57:52"
post_excerpt: ""
post_mime_type: ""
post_modified: "2018-02-10 08:57:52"
post_modified_gmt: "2018-02-10 08:57:52"
post_name: "13"
post_parent: 0
post_password: ""
post_status: "publish"
post_title: ""
post_type: "nav_menu_item"
target: ""
title: "About"
to_ping: ""
type: "post_type"
type_label: "Page"
url: "http://localhost:8888/learn-react/admin/about/"
xfn: ""

My problem is I’m trying to use this data to put a link on each menu item, but since I’m using React Router I don’t need the whole url (which is provided in the data above), but only the final slug. Here’s my menu component:

class MainMenu extends React.Component {

  componentDidMount() {
    this.props.fetchMainMenu();
  }

  render() {

    let menuItemsArray = store.getState().menuReducer.mainMenuItems;     
    let menuItems = menuItemsArray.map( ( menuItem, index ) => {    

      return( 
        <li key={ index }>
          <Link to={ menuItem.url }>{ menuItem.title }</Link>
        </li>
      )
    })
    return (
      <ul>{ menuItems }</ul>
    )
  }
}

Using menuItem.url generates the following href, of course:

http://localhost:3000/http://localhost:8888/learn-react/admin/about/

while, like I said, I would need something like menuItem.slug to generate:

http://localhost:3000/learn-react/admin/about/

What options do I have?

1 Answer
1

I had the same challenge, and fixed it by adding it to the response. Example:

function get_menu() {
    # Change 'menu' to your own navigation slug.
    $menu_items = wp_get_nav_menu_items('menu');
    foreach($menu_items as $menu_item) {
        // ALTERNATIVE: $slug = get_post_field( 'post_name', $menu_item->object_id );
        $slug = basename( get_permalink($menu_item->object_id) );
        $menu_item->slug = $slug;
    }
    return $menu_items;
}

add_action( 'rest_api_init', function () {
        register_rest_route( 'myroutes', '/menu', array(
        'methods' => 'GET',
        'callback' => 'get_menu',
    ) );
} );

Leave a Reply

Your email address will not be published. Required fields are marked *