Gutenberg - Where do we start?

Nicola Heald

will be doing the talking soon

Why Gutenberg?

Why now?

  • React Components
  • Block Attributes
  • Setting up an environment the easy way
  • Structure of a block
  • Putting it together
  • Demo: a simple block

A simple component

function Feeling( props ) {
	const { currentFeel } = props.attributes;
	return (
		<p>I am feeling { currentFeel }!</p>
	);
}

A React component can be as simple as a function that takes a properties object.

function Feeling( props ) {

A one of a block's properties is attributes.

These are key => value pairs that get serialised and stored with the block.

In this case, we are interested in the currentFeel attribute.

const { currentFeel } = props.attributes;

const is an ES6 variable that can't be reassigned.

We render the component as a paragraph.

	return (
		<p>I am feeling { currentFeel }!</p>
	);

Using a component

const attributes = { currentFeel: 'awesome' };
return (
	<Feeling attributes={ attribtues } />
);

I am feeling awesome!

Without JSX

var title = 'my link'; var url = 'http://notnownikki.com/';
return wp.element.createElement(
	'a',
	{ title: title, href: url },
	'My link'
);

With JSX

var title = 'my link'; var url = 'http://notnownikki.com/';
return <a href={ url } title={ title }>My link</a>;

Further reading: You Don't Know JavaScript - free book series taking you from the basics of JavaScript programming to the more complex ES6 syntax and concepts.

A JSX primer at StackChief.com

Components can be a lot more complex, responding to external events and having internal state, but for today let's stick with simple functions.

More to learn: The React "Getting Started" guide.

Setting up an ES6+JSX block development environment

ES6 still isn't understood by all browsers. We need our ES6 code translated into ES5.

JSX isn't understood by any browser. We need our JSX translated into ES5 JavaScript.

We also need some boilerplate that loads our block in a plugin.

Set up your JavaScript environment

  • Install nvm (already present on VVV)
    https://github.com/creationix/nvm
  • Update to the LTS version of Node
    $ nvm install lts/*
  • Activate the LTS version of Node
    $ nvm use lts/*

create-guten-block

create-guten-block is a tool that wraps up all the dependencies and boilerplate code into one neat environment and sets up everything you need without you having to set up babel, webpack, react libraries, etc.

Create a new plugin using create-guten-block

$ npx create-guten-block my-new-plugin

Start the development environment

$ cd my-new-plugin
$ npm start

Let's make a block!

Blocks have

  • Attributes.
  • An edit component that provides the editing UI.
  • A save component the generates the HTML to save in the post.

Example: a block that lets me select which programming language I'm using, and publishes how that's making me feel in the post.

Defining the attributes that the block has

const attributes = {
	currentFeel: {
		type: 'string'
	}
};

Attribute reference in the Gutenberg Handbook

The edit component

const edit = function( props ) {
	const { setAttributes } = props;
	const { currentFeel } = props.attributes;

	const setFeels = ( event ) => {
		setAttributes(
			{ currentFeel: event.target.value }
		);
	};

	return (
		<div className={ props.className }>
			<p>Today, I am writing <select onChange={ setFeels } value={ currentFeel }>
					<option></option>
					<option value="angry and tired">Perl</option>
					<option value="like I want to burn everything">C++</option>
					<option value="almost calm and approachable">JavaScript</option>
				</select>
			</p>
		</div>
	);
}

Define a new edit component

const edit = function( props ) {

A block's properties have a function for setting attributes. Using it makes sure that the editor is notified that the block has changed and the post is updated.

const { setAttributes } = props;

We get the currentFeel from the attributes so we can render the select control properly.

const { currentFeel } = props.attributes;

Define a function we can use to set the new attribute value when the select control changes.

const setFeels = ( event ) => {
	setAttributes(
		{ currentFeel: event.target.value }
	);
};

Arrow functions

Render the component as a prompt and a select control.

return (
	<div className={ props.className }>
		<p>Today, I am writing
			<select
				onChange={ setFeels } value={ currentFeel }>
				<option></option>
				<option value="angry and tired">Perl</option>
				<option value="like I want to burn everything">C++</option>
				<option value="almost calm and approachable">JavaScript</option>
			</select>
		</p>
	</div>
);

Define our save component

const save = function( props ) {
	const { currentFeel } = props.attributes;
	return (
		<p>Today, I am feeling { currentFeel }!</p>
	);
};

Register the block!

registerBlockType( 'wpmeetup/block-demo', {
	title: __( 'Feelings block' ),
	icon: 'shield',
	category: 'common',
	keywords: [
		__( 'How do I feel' ),
	],
	attributes: attributes,
	edit: edit,
	save: save,
} );

DEMO

Gutenberg Block Examples

Gutenberg Handbook

Getting started with React

create-guten-block

YDKJS


@notnownikki on twitter

slides available at http://notnownikki.com/talks/