A Practical Overview of the @wordpress/data API
- WordPress Data Series Overview and Introduction
- What is WordPress Data?
- WordPress Data: How to Register a Custom Store
- WordPress Data Interlude: Let’s talk Apps
- WordPress Data Store Properties: Actions
- WordPress Data Store Properties: Selectors
- WordPress Data Store Properties: Controls
- WordPress Data Store Properties: Resolvers
- WordPress Data Store Properties: Action Creator Generators
- WordPress Data Store Properties: Reducer
- WordPress Data: Putting it all together and registering your store!
- WordPress Data: Interfacing With the Store
- WordPress Data: Registry
- WordPress Data: Debugging Tips and Tools (draft)
- WordPress Data: Testing Tips (draft)
Now we have a resolver for asynchronously getting products via a REST api endpoint, we have some action creators, and we have a selector. We haven’t got to the reducer yet, but before we get to it, let’s consider another problem we haven’t addressed yet.
When we update or create a product using our ui, how are we going to persist that to the server? We could just wire up the POST
/PUT
endpoints directly in our component, but remember one of the reasons we’re implementing wp.data is to provide a common interface for any component needing to interact with the products data. So what can we do here?
Fortunately, we’ve covered a part of the wp.data api that provides us with a mechanism for doing this, controls. With controls, it is possible to make action creator generators that yield control action objects for handling asynchronous behaviour. Essentially everything you’ve learned about resolver generators so far can also be applied to action creators!
So let’s go back to the action creators we’ve already prepared (reminder: src/data/products/actions.js
) which are createProduct
, updateProduct
and deleteProduct
. Right now these are not wired up to any API route. Let’s change that. If you feel adventurous, why don’t you give it a go in your own fork of the app right now and see what you come up with. You can come back and see how close you got after.
You back? Okay, here’s one approach you could end up with:
import { getResourcePath } from './utils';
import { fetch } from '../controls';
import TYPES from './action-types';
const { UPDATE, CREATE, DELETE, HYDRATE } = TYPES;
export function* createProduct(product) {
const result = yield fetch(getResourcePath() + "/add", {
method: "POST",
body: product
});
if (result) {
return {
type: CREATE,
product: result
};
}
return;
}
export function* updateProduct(product) {
const result = yield fetch(getResourcePath(product.id), {
method: "PUT",
body: product
});
if (result) {
return {
type: UPDATE,
product
};
}
}
export function* deleteProduct(productId) {
const result = yield fetch(getResourcePath(productId), {
method: "DELETE"
});
if (result) {
return {
type: DELETE,
productId
};
}
}
Take note of a few things here:
- I’m using the
fetch
control (remember this from the post aboutresolvers
?) - I’m returning the original action object that was here before the updates.
Notice that the action creator is still returning an action object, the only change here is that with controls, we’re able to do some side-effects before returning that action object.
In the next post of this series, it’s time to go on to the last property of our store registration configuration object, the reducer.