diff --git a/docs/how-to-guides/data-basics/1-data-basics-setup.md b/docs/how-to-guides/data-basics/1-data-basics-setup.md
index 5e171577b40903..d9abd07967c8ce 100644
--- a/docs/how-to-guides/data-basics/1-data-basics-setup.md
+++ b/docs/how-to-guides/data-basics/1-data-basics-setup.md
@@ -163,29 +163,32 @@ add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' );
```json
{
- "name": "05-recipe-card-esnext",
- "version": "1.1.0",
- "private": true,
- "description": "Example: Recipe Card (ESNext).",
- "author": "The WordPress Contributors",
- "license": "GPL-2.0-or-later",
- "keywords": [ "WordPress", "block" ],
- "homepage": "https://github.com/WordPress/gutenberg-examples/",
- "repository": "git+https://github.com/WordPress/gutenberg-examples.git",
- "bugs": {
- "url": "https://github.com/WordPress/gutenberg-examples/issues"
- },
- "main": "build/index.js",
- "devDependencies": {
- "@wordpress/scripts": "^18.0.1"
- },
- "scripts": {
- "build": "wp-scripts build",
- "format": "wp-scripts format",
- "lint:js": "wp-scripts lint-js",
- "packages-update": "wp-scripts packages-update",
- "start": "wp-scripts start"
- }
+ "name": "09-code-data-basics-esnext",
+ "version": "1.1.0",
+ "private": true,
+ "description": "My first Gutenberg App",
+ "author": "The WordPress Contributors",
+ "license": "GPL-2.0-or-later",
+ "keywords": [
+ "WordPress",
+ "block"
+ ],
+ "homepage": "https://github.com/WordPress/gutenberg-examples/",
+ "repository": "git+https://github.com/WordPress/gutenberg-examples.git",
+ "bugs": {
+ "url": "https://github.com/WordPress/gutenberg-examples/issues"
+ },
+ "main": "build/index.js",
+ "devDependencies": {
+ "@wordpress/scripts": "^24.0.0"
+ },
+ "scripts": {
+ "build": "wp-scripts build",
+ "format": "wp-scripts format",
+ "lint:js": "wp-scripts lint-js",
+ "packages-update": "wp-scripts packages-update",
+ "start": "wp-scripts start"
+ }
}
```
@@ -209,4 +212,4 @@ Congratulations! You are now ready to start building the app!
- Previous part: [Introduction](/docs/how-to-guides/data-basics/README.md)
- Next part: [Building a basic list of pages](/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md)
-- (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/09-code-data-basics-esnext) in the gutenberg-examples repository
+- (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/non-block-examples/09-code-data-basics-esnext) in the gutenberg-examples repository
diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md
index c830e9d3b21bd7..e9d0c50d1d2113 100644
--- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md
+++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md
@@ -43,7 +43,7 @@ Before we start, let’s confirm we actually have some pages to fetch. Within WP
If it doesn’t, go ahead and create a few pages – you can use the same titles as on the screenshot above. Be sure to _publish_ and not just _save_ them.
-Now that we have the data to work with, let’s dive into the code. We will take advantage of the [`@wordpress/core-data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/core-data) package which provides resolvers, selectors, and actions to work with the WordPress core API. `@wordpress/core-data` builds on top of the [`@wordpress/data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/data).
+Now that we have the data to work with, let’s dive into the code. We will take advantage of the [`@wordpress/core-data`](https://github.com/WordPress/gutenberg/tree/trunk/packages/core-data) package which provides resolvers, selectors, and actions to work with the WordPress core API. `@wordpress/core-data` builds on top of the [`@wordpress/data`](https://github.com/WordPress/gutenberg/tree/trunk/packages/data) package.
To fetch the list of pages, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) selector. In broad strokes, it will issue the correct API request, cache the results, and return the list of the records we need. Here’s how to use it:
@@ -53,6 +53,8 @@ wp.data.select( 'core' ).getEntityRecords( 'postType', 'page' )
If you run that following snippet in your browser’s dev tools, you will see it returns `null`. Why? The pages are only requested by the `getEntityRecords` resolver after first running the _selector_. If you wait a moment and re-run it, it will return the list of all pages.
+*Note: To run this type of command directly make sure your browser is displaying an instance of the block editor (any page will do). Otherwise the `select( 'core' )` function won't be available, and you'll get an error.*
+
Similarly, the `MyFirstApp` component needs to re-run the selector once the data is available. That’s exactly what the `useSelect` hook does:
```js
@@ -67,6 +69,14 @@ function MyFirstApp() {
);
// ...
}
+
+function PagesList({ pages }) {
+ // ...
+
+ {page.title.rendered}
+
+ // ...
+}
```
Note that we use an `import` statement inside index.js. This enables the plugin to automatically load the dependencies using `wp_enqueue_script`. Any references to `coreDataStore` are compiled to the same `wp.data` reference we use in browser's devtools.
@@ -353,6 +363,7 @@ import { SearchControl, Spinner } from '@wordpress/components';
import { useState, render } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { store as coreDataStore } from '@wordpress/core-data';
+import { decodeEntities } from '@wordpress/html-entities';
function MyFirstApp() {
const [ searchTerm, setSearchTerm ] = useState( '' );
@@ -431,4 +442,4 @@ All that’s left is to refresh the page and enjoy the brand new status indicato
* **Previous part:** [Setup](/docs/how-to-guides/data-basics/1-data-basics-setup.md)
* **Next part:** [Building an edit form](/docs/how-to-guides/data-basics/3-building-an-edit-form.md)
-* (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/09-code-data-basics-esnext) in the gutenberg-examples repository
+* (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/non-block-examples/09-code-data-basics-esnext) in the gutenberg-examples repository
diff --git a/docs/how-to-guides/data-basics/3-building-an-edit-form.md b/docs/how-to-guides/data-basics/3-building-an-edit-form.md
index 6fd8be0f75d4ca..754a31f1bc4921 100644
--- a/docs/how-to-guides/data-basics/3-building-an-edit-form.md
+++ b/docs/how-to-guides/data-basics/3-building-an-edit-form.md
@@ -59,7 +59,7 @@ Our button looks nice but doesn't do anything yet. To display an edit form, we n
```js
import { Button, TextControl } from '@wordpress/components';
-export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
+function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
return (
select( coreDataStore ).getEntityRecord( 'postType', 'page', pageId ),
[pageId]
@@ -140,7 +140,7 @@ export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
{ /* ... */ }
@@ -148,7 +148,7 @@ export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
}
```
-Now it should look like that:
+Now it should look like this:
![](https://raw.githubusercontent.com/WordPress/gutenberg/HEAD/docs/how-to-guides/data-basics/media/edit-form/form-populated.png)
@@ -160,7 +160,7 @@ There's one problem with our _Page title_ field: you can't edit it. It receives
You may have seen a pattern similar to this one in other React apps. It's known as a ["controlled component"](https://reactjs.org/docs/forms.html#controlled-components):
```js
-export function VanillaReactForm({ initialTitle }) {
+function VanillaReactForm({ initialTitle }) {
const [title, setTitle] = useState( initialTitle );
return (
select( coreDataStore ).getEditedEntityRecord( 'postType', 'page', pageId ),
[ pageId ]
@@ -281,7 +281,7 @@ Entity records are updated to reflect any saved changes right after the REST API
This is how the `EditPageForm` looks like with a working *Save* button:
```js
-export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
+function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
// ...
const { saveEditedEntityRecord } = useDispatch( coreDataStore );
const handleSave = () => saveEditedEntityRecord( 'postType', 'page', pageId );
@@ -303,7 +303,7 @@ export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
It works, but there's still one thing to fix: the form modal doesn't automatically close because we never call `onSaveFinished`. Lucky for us, `saveEditedEntityRecord` returns a promise that resolves once the save operation is finished. Let's take advantage of it in `EditPageForm`:
```js
-export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
+function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
// ...
const handleSave = async () => {
await saveEditedEntityRecord( 'postType', 'page', pageId );
@@ -324,7 +324,7 @@ We optimistically assumed that a *save* operation would always succeed. Unfortun
To tell the user when any of these happens, we have to make two adjustments. We don't want to close the form modal when the update fails. The promise returned by `saveEditedEntityRecord` is resolved with an updated record only if the update actually worked. When something goes wrong, it resolves with an empty value. Let's use it to keep the modal open:
```js
-export function EditPageForm( { pageId, onSaveFinished } ) {
+function EditPageForm( { pageId, onSaveFinished } ) {
// ...
const handleSave = async () => {
const updatedRecord = await saveEditedEntityRecord( 'postType', 'page', pageId );
@@ -346,7 +346,7 @@ wp.data.select( 'core' ).getLastEntitySaveError( 'postType', 'page', 9 )
Here's how we can use it in `EditPageForm`:
```js
-export function EditPageForm( { pageId, onSaveFinished } ) {
+function EditPageForm( { pageId, onSaveFinished } ) {
// ...
const { lastError, page } = useSelect(
select => ({
@@ -357,7 +357,7 @@ export function EditPageForm( { pageId, onSaveFinished } ) {
)
// ...
return (
- <>
+
{/* ... */}
{ lastError ? (
@@ -365,7 +365,7 @@ export function EditPageForm( { pageId, onSaveFinished } ) {
) : false }
{/* ... */}
- >
+
);
}
```
@@ -375,7 +375,7 @@ Great! `EditPageForm` is now fully aware of errors.
Let's see that error message in action. We'll trigger an invalid update and let it fail. The post title is hard to break, so let's set a `date` property to `-1` instead – that's a guaranteed validation error:
```js
-export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
+function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
// ...
const handleChange = ( title ) => editEntityRecord( 'postType', 'page', pageId, { title, date: -1 } );
// ...
@@ -397,7 +397,7 @@ We're going to clear it up and communicate two states to the user: _Saving_ and
Let's use them in `EditPageForm`:
```js
-export function EditPageForm( { pageId, onSaveFinished } ) {
+function EditPageForm( { pageId, onSaveFinished } ) {
// ...
const { isSaving, hasEdits, /* ... */ } = useSelect(
select => ({
@@ -413,8 +413,7 @@ export function EditPageForm( { pageId, onSaveFinished } ) {
We can now use `isSaving` and `hasEdits` to display a spinner when saving is in progress and grey out the save button when there are no edits:
```js
-
-export function EditPageForm( { pageId, onSaveFinished } ) {
+function EditPageForm( { pageId, onSaveFinished } ) {
// ...
return (
// ...
@@ -479,7 +478,7 @@ function PageEditButton( { pageId } ) {
);
}
-export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
+function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
const { page, lastError, isSaving, hasEdits } = useSelect(
( select ) => ( {
page: select( coreDataStore ).getEditedEntityRecord( 'postType', 'page', pageId ),
@@ -541,4 +540,4 @@ export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
* **Previous part:** [Building a list of pages](/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md)
* **Next part:** Building a *New Page* form (coming soon)
-* (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/09-code-data-basics-esnext) in the gutenberg-examples repository
+* (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/non-block-examples/09-code-data-basics-esnext) in the gutenberg-examples repository
diff --git a/docs/how-to-guides/data-basics/4-building-a-create-page-form.md b/docs/how-to-guides/data-basics/4-building-a-create-page-form.md
index 36937974d118da..19aada07c2fc78 100644
--- a/docs/how-to-guides/data-basics/4-building-a-create-page-form.md
+++ b/docs/how-to-guides/data-basics/4-building-a-create-page-form.md
@@ -68,7 +68,7 @@ Now that the button is in place, we can focus entirely on building the form. Thi
Luckily, the `EditPageForm` we built in [part three](/docs/how-to-guides/data-basics/3-building-an-edit-form.md) already takes us 80% of the way there. The bulk of the user interface is already available, and we will reuse it in the `CreatePageForm`. Let’s start by extracting the form UI into a separate component:
```js
-export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
+function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
// ...
return (
setTitle( title );
return (
@@ -180,7 +180,7 @@ Triggers a POST request to the [`/wp/v2/pages` WordPress REST API](https://devel
Now that we know more about `saveEntityRecord`, let's use it in `CreatePageForm`.
```js
-export function CreatePageForm( { onSaveFinished, onCancel } ) {
+function CreatePageForm( { onSaveFinished, onCancel } ) {
// ...
const { saveEntityRecord } = useDispatch( coreDataStore );
const handleSave = async () => {
@@ -206,7 +206,7 @@ export function CreatePageForm( { onSaveFinished, onCancel } ) {
There is one more detail to address: our newly created pages are not yet picked up by the `PagesList`. Accordingly to the REST API documentation, the `/wp/v2/pages` endpoint creates (`POST` requests) pages with `status=draft` by default, but _returns_ (`GET` requests) pages with `status=publish`. The solution is to pass the `status` parameter explicitly:
```js
-export function CreatePageForm( { onSaveFinished, onCancel } ) {
+function CreatePageForm( { onSaveFinished, onCancel } ) {
// ...
const { saveEntityRecord } = useDispatch( coreDataStore );
const handleSave = async () => {
@@ -238,7 +238,7 @@ The `EditPageForm` retrieved the error and progress information via the `getLas
In `CreatePageForm` however, we do not have a `pageId`. What now? We can skip the `pageId` argument to retrieve the information about the entity record without any id – this will be the newly created one. The `useSelect` call is thus very similar to the one from `EditPageForm`:
```js
-export function CreatePageForm( { onCancel, onSaveFinished } ) {
+function CreatePageForm( { onCancel, onSaveFinished } ) {
// ...
const { lastError, isSaving } = useSelect(
( select ) => ( {
@@ -272,7 +272,7 @@ And that’s it! Here's what our new form looks like in action:
Here’s everything we built in this chapter in one place:
```js
-export function CreatePageForm( { onCancel, onSaveFinished } ) {
+function CreatePageForm( { onCancel, onSaveFinished } ) {
const [title, setTitle] = useState();
const { lastError, isSaving } = useSelect(
( select ) => ( {
@@ -309,7 +309,7 @@ export function CreatePageForm( { onCancel, onSaveFinished } ) {
);
}
-export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
+function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
const { page, lastError, isSaving, hasEdits } = useSelect(
( select ) => ( {
page: select( coreDataStore ).getEditedEntityRecord( 'postType', 'page', pageId ),
@@ -342,7 +342,7 @@ export function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
);
}
-export function PageForm( { title, onChangeTitle, hasEdits, lastError, isSaving, onCancel, onSave } ) {
+function PageForm( { title, onChangeTitle, hasEdits, lastError, isSaving, onCancel, onSave } ) {
return (
{ decodeEntities( page.title.rendered ) }
-
+
{/* ↓ This is the only change in the PagesList component */}
- {/* ↑ This is the only change in the PagesList component */}
|
@@ -285,7 +284,7 @@ function DeletePageButton( { pageId } ) {
Great! `DeletePageButton` is now fully aware of errors. Let's see that error message in action. We'll trigger an invalid delete and let it fail. One way to do this is to multiply the `pageId` by a large number:
```js
-export function DeletePageButton( { pageId, onCancel, onSaveFinished } ) {
+function DeletePageButton( { pageId, onCancel, onSaveFinished } ) {
pageId = pageId * 1000;
// ...
}
@@ -447,4 +446,4 @@ function DeletePageButton( { pageId } ) {
## What's next?
* **Previous part:** [Building a *Create page form*](/docs/how-to-guides/data-basics/4-building-a-create-page-form.md)
-* (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/09-code-data-basics-esnext) in the gutenberg-examples repository
+* (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/non-block-examples/09-code-data-basics-esnext) in the gutenberg-examples repository