How do I add woocommerce endpoint to the state?

I’m sorry, I can’t get the result I expect… :sleepy:

If I access the following endpoint I get all the data I need:
https://wp.laotramirada.com.uy/wp-json/wc/v3/products

How do I add the endpoint to the state?

Thank you!!

Hi @vscopise! :wave:

In order to fetch that data and put it in the state you should do a api.get() followed by api.populate as described in the docs

@vscopise are you trying to create an E-commerce with Frontity? :smile:

Unfortunately the woocommerce API requires authentication, so it cannot be used in the client.

As far as I know the only API available to do so is the one of CoCart but we haven’t explored it yet.

Apart from that, if you want that data to be related to a URL or set of URLs, you need to use those methods (the ones @mmczaplinski told you) inside a handler.

These are the current documentation for handlers:
https://docs.frontity.org/api-reference-1/wordpress-source

Let us know if you have any questions.

So super dangerous suggestion but one that could work in production IF you lock down the wordpress site with some toight toight security (IP whitelisting, CORS policies, and whatever else you can throw at it).

You can disable woocommerce authentication: https://www.damiencarbery.com/2019/07/disable-woocommerce-rest-api-authentication/

I’m not recommending this (just yet) until I get to play around with it but could be a solution with appropriate, alternative security in place.

You can get all the product data, but it requires a bit of customization,

function pxe_wce_rest_check_permissions() {
return true;
}
add_filter( 'woocommerce_rest_check_permissions', 'pxe_wce_rest_check_permissions' );

i recomend to read this to the cart manage

3 Likes

That article has blown my mind

:wink:

1 Like

Really good article, thanks @vscopise.

For simple carts like his, that approach can work really well. Creating a cart with Frontity’s state and actions should be fairly easy (please use derived state, don’t duplicate it).

For more complex carts, I guess you don’t want to reinvent the wheel. The WooCommerce cart already has many features with lots of logic (think of coupons, stock and so on) that are best managed in the WordPress dashboard.

By the way, he is exposing the consumer and secret keys in the client. I’m not expert in security but it doesn’t seem like a good idea to me… Be careful with that :sweat_smile:

1 Like

Very fair points. I was excited by his how logic unfolds but ya - as usual I need to sleep on it and test in the real world thoroughly before I inevitably come to the conclusions you pointed out @luisherranz :joy: you buzzkill :rofl::rofl:

I’m really sorry, I didn’t mean that create a client-side cart is a bad option! I actually think it’s a very good one if you have a simple cart :slight_smile: (and thanks to @vscopise for bringing it up)

1 Like

Na, you were very clear it’s an interesting method. Really valid points you added.

1 Like

Wow! This article is great

I can get all products using custom post types as indicated here,
but to get all the necessary data I need to use this url,

I think I need a handler but it is not clear how to implement it.

Should I do it in frontity.settings.js?
in index.js?
in the component that shows products?

Thank you !!

Hi @vscopise!

I’ll recommend you to create it at the index.js file of the theme you are using. And in case you are planning to use more than one handler you could create a separate folder or file and import them from your index.js. It should look something similar to this:

const productsHandler = {
  name: "products",
  priority: 10,
  pattern: "products/:slug", //Or whatever your pattern is
  func: async () => { 
    ...
  };
}

const marsTheme = {
  name: "@frontity/mars-theme",
  roots: { ... },
  state: { ... },
  actions: { ... },
  libraries: {
    ...
    source: {
      handlers: [productsHandler]
    }
  }
};

export default marsTheme;

You can take a deeper look on handlers at our documentation.

Once you’ve created the handler, if you navigate to an url with the pattern you defined (products/slug/ for example), Frontity will run the function you defined and it should store the data in the state.

After that, you just have to get that data in the component you need it, using something like this:

const Product = ({ state, actions, libraries }) => {
  // Get information about the current URL.
  const data = state.source.get(state.router.link);

  ... //Use the data as you want

}

export default connect(Product);

If you are planning to use a template just for products, you could add something like isProduct equals true in the handler function as well, so you can filter it in your theme:

...
{
  (data.isFetching && <Loading />) ||
  (data.isArchive && <List />) ||
  (data.isProduct && <Product />) ||
  (data.isPostType && <Post />) ||
  (data.is404 && <Page404 />)
}
...

Please, let us know if this helps you and if you have more questions about this we’ll be glad to help :slightly_smiling_face:.

1 Like

Hi SantosGuillamot !

I realize that there’s a problem with the endpoint

when I navigate to /product i get this message:
`

Error: post type from endpoints “posts,pages,media” with slug “product” not found

`
In Postman I can get the data:
https://wp.laotramirada.com.uy/wp-json/wp/v2/product/

in frontity.settings I have:

...
postTypes: [
   {
     type: 'product',
     endpoint: 'product',
   }
]

I’m sorry,
I realized that I was putting the wrong data in frontity.settings,

the correct way is:

...
state: {
   source: {
     api: "https://wp.laotramirada.com.uy/wp-json",
     postTypes: [
       {
         type: 'product',
         endpoint: 'product',
         archive: 'product',
       }
     ]              
   },
 }
...

Should I combine a handler with postTypes to get all the necessary data?

Not sure if combining the handler with postTypes will work. I think the best option is to choose between:

  • Using a custom endpoint and use a handler to point to that data.
  • Using the CPT product and add more info (if necessary) from your WordPress.

Just to clarify it a bit more we have two cases:

If you use the CPT you defined

With that settings, you are telling Frontity to fetch that CPT. As you have defined it:

  • If you access to https://mysite.com/product/first-product (from Frontity) you’ll be getting the info from the endpoint https://wp.mysite.com/wp-json/wp/v2/product?slug=first-product (from your WP).
  • If you access to https://mysite.com/product you’ll be getting a list of all your products, fetched from https://wp.mysite.com/wp-json/wp/v2/product?slug=first-product.

You could add more info to that endpoint from your WP.

If you use your own handler

We usually use handlers to fetch data from a custom endpoint, or to change the way we populate the state.

With the handler you are telling Frontity: if we access the url https://mysite.com/products/slug you are going to run the function defined inside it. Inside this function, we usually fetch data from a new endpoint, and how we populate the frontity.state in order to consume that info later.

If you want to show a lists of your products when you access https://mysite.com/products, you’d need to create a new handler to match that pattern, and fetch all the products from your endpoint.

You’d need a new handler for example if you want to point to woocommerce API instead of wp-json/wp/v2.


In this case, if you’re fetching the data from a CPT, I guess the best option would be to use the CPT without a handler. And if you want to fetch the data from a different endpoint you may want to use a handler.

Let us know if this info helps you :slightly_smiling_face:

Hi Mario,
If I access to /product/polo I get “is404”… :sleepy:

I’ve created a repo to share the code if you have time to see it

thks

I found a handler to get all data:

const homeHandler = {
  name: 'home',
  priority: 20,
  pattern: '/',

  func: async ({ route, params, state, libraries }) => {
    // 1. get products data
    const response = await libraries.source.api.get({
      endpoint: '/wc/v3/products',
    });

    // 2. add product to state
    const productsData = await response.json();

    // 3. add route to data
    Object.assign(state.source.data[route], {
      productsData,
      isHome: true
    });
  }
}

With the products in the state,
I can implement operations such as adding to the cart, generating the order, etc.

I update when I have progress :smiley:

5 Likes