Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the documentation of the block editor and replace @wordpress/element with react #54908

Merged
merged 7 commits into from Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/contributors/code/coding-guidelines.md
Expand Up @@ -529,7 +529,7 @@ alert( `My name is ${ name }.` );
- Example: `document.body.classList.toggle( 'has-focus', nodeRef.current?.contains( document.activeElement ) );` may wrongly _add_ the class, since [the second argument is optional](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle). If `undefined` is passed, it would not unset the class as it would when `false` is passed.
- Example: `<input value={ state.selected?.value.trim() } />` may inadvertently cause warnings in React by toggling between [controlled and uncontrolled inputs](https://reactjs.org/docs/uncontrolled-components.html). This is an easy trap to fall into when eagerly assuming that a result of `trim()` will always return a string value, overlooking the fact the optional chaining may have caused evaluation to abort earlier with a value of `undefined`.

### `@wordpress/element` (React) Components
### React Components

It is preferred to implement all components as [function components](https://reactjs.org/docs/components-and-props.html), using [hooks](https://reactjs.org/docs/hooks-reference.html) to manage component state and lifecycle. With the exception of [error boundaries](https://reactjs.org/docs/error-boundaries.html), you should never encounter a situation where you must use a class component. Note that the [WordPress guidance on Code Refactoring](https://make.wordpress.org/core/handbook/contribute/code-refactoring/) applies here: There needn't be a concentrated effort to update class components in bulk. Instead, consider it as a good refactoring opportunity in combination with some other change.

Expand Down Expand Up @@ -756,7 +756,7 @@ When documenting an example, use the markdown <code>\`\`\`</code> code block to
*/
````

### Documenting `@wordpress/element` (React) Components
### Documenting React Components

When possible, all components should be implemented as [function components](https://reactjs.org/docs/components-and-props.html#function-and-class-components), using [hooks](https://reactjs.org/docs/hooks-intro.html) for managing component lifecycle and state.

Expand Down
2 changes: 1 addition & 1 deletion docs/contributors/code/scripts.md
Expand Up @@ -23,7 +23,7 @@ The editor includes a number of packages to enable various pieces of functionali
| [Dom Ready](/packages/dom-ready/README.md) | wp-dom-ready | Execute callback after the DOM is loaded |
| [Editor](/packages/editor/README.md) | wp-editor | Building blocks for WordPress editors |
| [Edit Post](/packages/edit-post/README.md) | wp-edit-post | Edit Post Module for WordPress |
| [Element](/packages/element/README.md) | wp-element | Element is, quite simply, an abstraction layer atop [React](https://reactjs.org/) |
| [Element](/packages/element/README.md) | wp-element | Element is a set of utilities to work with [React](https://reactjs.org/) elements and components |
youknowriad marked this conversation as resolved.
Show resolved Hide resolved
| [Escape Html](/packages/escape-html/README.md) | wp-escape-html | Escape HTML utils |
| [Hooks](/packages/hooks/README.md) | wp-hooks | A lightweight and efficient EventManager for JavaScript |
| [Html Entities](/packages/html-entities/README.md) | wp-html-entities | HTML entity utilities for WordPress |
Expand Down
2 changes: 1 addition & 1 deletion docs/explanations/architecture/modularity.md
Expand Up @@ -43,7 +43,7 @@ function MyApp() {
```php
// myplugin.php
// Example of script registration dependending on the "components" and "element packages.
wp_register_script( 'myscript', 'pathtomyscript.js', array ('wp-components', "wp-element" ) );
wp_register_script( 'myscript', 'pathtomyscript.js', array ('wp-components', "react" ) );
```

```js
Expand Down
Expand Up @@ -58,8 +58,8 @@ registerBlockType( 'gutenberg-examples/example-02-stylesheets', {
{% Plain %}

```js
( function ( blocks, element, blockEditor ) {
var el = element.createElement;
( function ( blocks, React, blockEditor ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is uppercase also how the default React scripts adds the window variable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

var el = React.createElement;

blocks.registerBlockType( 'gutenberg-examples/example-02-stylesheets', {
edit: function ( props ) {
Expand Down Expand Up @@ -93,7 +93,7 @@ registerBlockType( 'gutenberg-examples/example-02-stylesheets', {
);
},
} );
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor );
} )( window.wp.blocks, window.React, window.wp.blockEditor );
```

{% end %}
Expand Down Expand Up @@ -134,8 +134,8 @@ registerBlockType( 'gutenberg-examples/example-02-stylesheets', {
{% Plain %}

```js
( function ( blocks, element, blockEditor ) {
var el = element.createElement;
( function ( blocks, React, blockEditor ) {
var el = React.createElement;

blocks.registerBlockType( 'gutenberg-examples/example-02-stylesheets', {
edit: function ( props ) {
Expand All @@ -155,7 +155,7 @@ registerBlockType( 'gutenberg-examples/example-02-stylesheets', {
);
},
} );
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor );
} )( window.wp.blocks, window.React, window.wp.blockEditor );
```

{% end %}
Expand All @@ -180,8 +180,8 @@ Edit the asset file to include the block-editor dependency for the scripts.
<?php return
array( 'dependencies' =>
array(
'react',
'wp-blocks',
'wp-element',
'wp-block-editor',
'wp-polyfill'
),
Expand Down
Expand Up @@ -95,8 +95,8 @@ registerBlockType( 'gutenberg-examples/example-04-controls-esnext', {
{% Plain %}

```js
( function ( blocks, blockEditor, element ) {
var el = element.createElement;
( function ( blocks, blockEditor, React ) {
var el = React.createElement;
var RichText = blockEditor.RichText;
var AlignmentToolbar = blockEditor.AlignmentToolbar;
var BlockControls = blockEditor.BlockControls;
Expand Down Expand Up @@ -176,7 +176,7 @@ registerBlockType( 'gutenberg-examples/example-04-controls-esnext', {
);
},
} );
} )( window.wp.blocks, window.wp.blockEditor, window.wp.element );
} )( window.wp.blocks, window.wp.blockEditor, window.React );
```

{% end %}
Expand Down
Expand Up @@ -67,8 +67,8 @@ registerBlockType( 'gutenberg-examples/example-03-editable-esnext', {
{% Plain %}

```js
( function ( blocks, blockEditor, element ) {
var el = element.createElement;
( function ( blocks, blockEditor, React ) {
var el = React.createElement;
var RichText = blockEditor.RichText;
var useBlockProps = blockEditor.useBlockProps;

Expand Down Expand Up @@ -118,7 +118,7 @@ registerBlockType( 'gutenberg-examples/example-03-editable-esnext', {
);
},
} );
} )( window.wp.blocks, window.wp.blockEditor, window.wp.element );
} )( window.wp.blocks, window.wp.blockEditor, window.React );
```

{% end %}
Expand Down
12 changes: 6 additions & 6 deletions docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md
Expand Up @@ -55,8 +55,8 @@ registerBlockType( 'gutenberg-examples/example-dynamic', {
{% Plain %}

```js
( function ( blocks, element, data, blockEditor ) {
var el = element.createElement,
( function ( blocks, React, data, blockEditor ) {
var el = React.createElement,
registerBlockType = blocks.registerBlockType,
useSelect = data.useSelect,
useBlockProps = blockEditor.useBlockProps;
Expand Down Expand Up @@ -86,7 +86,7 @@ registerBlockType( 'gutenberg-examples/example-dynamic', {
} );
} )(
window.wp.blocks,
window.wp.element,
window.React,
window.wp.data,
window.wp.blockEditor
);
Expand Down Expand Up @@ -187,8 +187,8 @@ registerBlockType( 'gutenberg-examples/example-dynamic', {
{% Plain %}

```js
( function ( blocks, element, serverSideRender, blockEditor ) {
var el = element.createElement,
( function ( blocks, React, serverSideRender, blockEditor ) {
var el = React.createElement,
registerBlockType = blocks.registerBlockType,
ServerSideRender = serverSideRender,
useBlockProps = blockEditor.useBlockProps;
Expand All @@ -213,7 +213,7 @@ registerBlockType( 'gutenberg-examples/example-dynamic', {
} );
} )(
window.wp.blocks,
window.wp.element,
window.React,
window.wp.serverSideRender,
window.wp.blockEditor
);
Expand Down
Expand Up @@ -111,8 +111,8 @@ registerBlockType( 'gutenberg-examples/example-03-editable-esnext', {
{% Plain %}

```js
( function ( blocks, blockEditor, element ) {
var el = element.createElement;
( function ( blocks, blockEditor, React ) {
var el = React.createElement;
var RichText = blockEditor.RichText;
var useBlockProps = blockEditor.useBlockProps;

Expand Down Expand Up @@ -162,7 +162,7 @@ registerBlockType( 'gutenberg-examples/example-03-editable-esnext', {
);
},
} );
} )( window.wp.blocks, window.wp.blockEditor, window.wp.element );
} )( window.wp.blocks, window.wp.blockEditor, window.React );
```

{% end %}
24 changes: 12 additions & 12 deletions docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
Expand Up @@ -41,8 +41,8 @@ registerBlockType( 'gutenberg-examples/example-06', {
{% Plain %}

```js
( function ( blocks, element, blockEditor ) {
var el = element.createElement;
( function ( blocks, React, blockEditor ) {
var el = React.createElement;
var InnerBlocks = blockEditor.InnerBlocks;
var useBlockProps = blockEditor.useBlockProps;

Expand All @@ -62,7 +62,7 @@ registerBlockType( 'gutenberg-examples/example-06', {
return el( 'div', blockProps, el( InnerBlocks.Content ) );
},
} );
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor );
} )( window.wp.blocks, window.React, window.wp.blockEditor );
```

{% end %}
Expand Down Expand Up @@ -241,8 +241,8 @@ registerBlockType( 'gutenberg-examples/example-06', {
{% Plain %}

```js
( function ( blocks, element, blockEditor ) {
var el = element.createElement;
( function ( blocks, React, blockEditor ) {
var el = React.createElement;
var InnerBlocks = blockEditor.InnerBlocks;
var useBlockProps = blockEditor.useBlockProps;
var useInnerBlocksProps = blockEditor.useInnerBlocksProps;
Expand All @@ -265,7 +265,7 @@ registerBlockType( 'gutenberg-examples/example-06', {
return el( 'div', blockProps, el( 'div', innerBlocksProps ) );
},
} );
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor );
} )( window.wp.blocks, window.React, window.wp.blockEditor );
```

{% end %}
Expand Down Expand Up @@ -305,8 +305,8 @@ registerBlockType( 'gutenberg-examples/example-06', {
{% Plain %}

```js
( function ( blocks, element, blockEditor ) {
var el = element.createElement;
( function ( blocks, React, blockEditor ) {
var el = React.createElement;
var InnerBlocks = blockEditor.InnerBlocks;
var useBlockProps = blockEditor.useBlockProps;
var useInnerBlocksProps = blockEditor.useInnerBlocksProps;
Expand All @@ -328,7 +328,7 @@ registerBlockType( 'gutenberg-examples/example-06', {
return el( 'div', innerBlocksProps );
},
} );
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor );
} )( window.wp.blocks, window.React, window.wp.blockEditor );
```

{% end %}
Expand Down Expand Up @@ -372,8 +372,8 @@ registerBlockType( 'gutenberg-examples/example-06', {
{% Plain %}

```js
( function ( blocks, element, blockEditor ) {
var el = element.createElement;
( function ( blocks, React, blockEditor ) {
var el = React.createElement;
var InnerBlocks = blockEditor.InnerBlocks;
var useBlockProps = blockEditor.useBlockProps;
var useInnerBlocksProps = blockEditor.useInnerBlocksProps;
Expand All @@ -398,7 +398,7 @@ registerBlockType( 'gutenberg-examples/example-06', {
},
// ...
} );
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor );
} )( window.wp.blocks, window.React, window.wp.blockEditor );
```

{% end %}
Expand Down
Expand Up @@ -145,8 +145,8 @@ registerBlockType( 'gutenberg-examples/example-01-basic-esnext', {
Add the following to `block.js`

```js
( function ( blocks, element ) {
var el = element.createElement;
( function ( blocks, React ) {
var el = React.createElement;

blocks.registerBlockType( 'gutenberg-examples/example-01-basic', {
edit: function () {
Expand All @@ -156,7 +156,7 @@ Add the following to `block.js`
return el( 'p', {}, 'Hola mundo (from the frontend).' );
},
} );
} )( window.wp.blocks, window.wp.element );
} )( window.wp.blocks, window.React );
```

{% end %}
Expand All @@ -182,8 +182,8 @@ Create the asset file to load the dependencies for the scripts. The name of this
<?php return
array( 'dependencies' =>
array(
'react',
'wp-blocks',
'wp-element',
'wp-polyfill'
),
'version' => '0.1'
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to-guides/data-basics/1-data-basics-setup.md
Expand Up @@ -18,7 +18,7 @@ Go ahead and create these files using the following snippets:
**src/index.js:**

```js
import { render } from '@wordpress/element';
import { render } from 'react-dom';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we update that to reflect that we're now using React 18? Same for all other render() instances.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There something subtle here is that we should do import { createRoot } from 'react-dom' instead of import { createRoot } from 'react-com/client'.

I think that's not great but it's because of how wp-scripts works at the moment. Basically it transforms react-dom imports to ReactDOM global variable and adds the wp dependency to the php script. And because of React generates the build we use, it works because createRoot is actually ReactDOM.createRoot in that build.

I think that's very confusing but I don't plan on solving that in this PR.


function MyFirstApp() {
return <span>Hello from JavaScript!</span>;
Expand Down
Expand Up @@ -150,8 +150,8 @@ The list of pages is short for now; however, the longer it grows, the harder it
Let’s start by adding a search field:

```js
import { useState } from 'react';
import { SearchControl } from '@wordpress/components';
import { useState, render } from '@wordpress/element';

function MyFirstApp() {
const [searchTerm, setSearchTerm] = useState( '' );
Expand Down Expand Up @@ -211,8 +211,9 @@ The `searchTerm` is now used as a `search` query parameter when provided. Note t
Finally, here’s how `MyFirstApp` looks once we wire it all together:

```js
import { useState } from 'react';
import { render } from 'react-dom';
import { SearchControl } from '@wordpress/components';
import { useState, render } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { store as coreDataStore } from '@wordpress/core-data';

Expand Down Expand Up @@ -359,8 +360,8 @@ And voilà! That's it.
All the pieces are in place, great! Here’s the complete JavaScript code of our app:

```js
import { useState } from 'react';
youknowriad marked this conversation as resolved.
Show resolved Hide resolved
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';
Expand Down
6 changes: 3 additions & 3 deletions docs/how-to-guides/data-basics/5-adding-a-delete-button.md
Expand Up @@ -142,7 +142,7 @@ wp.data.select( 'core' ).getLastEntityDeleteError( 'postType', 'page', 9 )
Here's how we can apply it in `DeletePageButton`:

```js
import { useEffect } from '@wordpress/element';
import { useEffect } from 'react';
const DeletePageButton = ({ pageId }) => {
// ...
const { error, /* ... */ } = useSelect(
Expand Down Expand Up @@ -252,8 +252,8 @@ Now we're ready to tell the user about any errors that may have occurred.
With the SnackbarNotices component in place, we're ready to dispatch some notifications! Here's how:

```js
import { useEffect } from 'react';
import { store as noticesStore } from '@wordpress/notices';
import { useEffect } from '@wordpress/element';
function DeletePageButton( { pageId } ) {
const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore );
// useSelect returns a list of selectors if you pass the store handle
Expand Down Expand Up @@ -307,8 +307,8 @@ And that's it!
All the pieces are in place, great! Here’s all the changes we've made in this chapter:

```js
import { useState, useEffect } from 'react';
import { useSelect, useDispatch } from '@wordpress/data';
import { useState, useEffect } from '@wordpress/element';
import { Button, Modal, TextControl } from '@wordpress/components';

function MyFirstApp() {
Expand Down
4 changes: 2 additions & 2 deletions docs/how-to-guides/internationalization.md
Expand Up @@ -24,7 +24,7 @@ function myguten_block_init() {
wp_register_script(
'myguten-script',
plugins_url( 'block.js', __FILE__ ),
array( 'wp-blocks', 'wp-element', 'wp-i18n', 'wp-block-editor' )
array( 'wp-blocks', 'react', 'wp-i18n', 'wp-block-editor' )
);

register_block_type( 'myguten/simple', array(
Expand Down Expand Up @@ -67,8 +67,8 @@ registerBlockType( 'myguten/simple', {
{% Plain %}

```js
const el = React.createElement;
const { __ } = wp.i18n;
const el = wp.element.createElement;
const { registerBlockType } = wp.blocks;
const { useBlockProps } = wp.blockEditor;

Expand Down
2 changes: 1 addition & 1 deletion docs/how-to-guides/javascript/js-build-setup.md
Expand Up @@ -153,7 +153,7 @@ Likewise, you do not need to include `node_modules` or any of the above configur
## Dependency Management

Using `wp-scripts` ver 5.0.0+ build step will also produce an `index.asset.php` file that contains an array of dependencies and a version number for your block. For our simple example above, it is something like:
`array('dependencies' => array('wp-element', 'wp-polyfill'), 'version' => 'fc93c4a9675c108725227db345898bcc');`
`array('dependencies' => array('react', 'wp-polyfill'), 'version' => 'fc93c4a9675c108725227db345898bcc');`

Here is how to use this asset file to automatically set the dependency list for enqueuing the script. This prevents having to manually update the dependencies, it will be created based on the package imports used within your block.

Expand Down