Skip to main content
Block context enables ancestor blocks to provide values that descendent blocks within their hierarchy can consume. This allows blocks to share data without hard-coded values or explicit awareness of the provider.

Overview

Block context is especially useful in full-site editing where block content may depend on the context of the post in which it’s displayed. For example, a blogroll template showing multiple posts can use a single “Post Excerpt” block that displays content based on an inherited post ID. If you’re familiar with React Context, block context adopts similar concepts. The client-side implementation uses React Context, and context is also supported in server-side render_callback functions.

Providing context

A block provides context by mapping a context name to one of its attributes using the providesContext property.

In block.json

{
	"attributes": {
		"recordId": {
			"type": "number"
		}
	},
	"providesContext": {
		"my-plugin/recordId": "recordId"
	}
}

In JavaScript

registerBlockType( 'my-plugin/record', {
	attributes: {
		recordId: {
			type: 'number'
		}
	},
	providesContext: {
		'my-plugin/recordId': 'recordId'
	}
} );
Include a namespace in context names (e.g., my-plugin/recordId) to avoid conflicts with other plugins or WordPress core.

Consuming context

A block consumes context by declaring the context names it needs in the usesContext array.

In block.json

{
	"usesContext": ["my-plugin/recordId"]
}

In JavaScript

registerBlockType( 'my-plugin/record-title', {
	title: 'Record Title',
	category: 'widgets',
	usesContext: [ 'my-plugin/recordId' ]
} );

Using context values

Once declared, context values are accessible in both JavaScript and PHP implementations.

JavaScript (edit function)

Context is provided as a property to the edit function:
registerBlockType( 'my-plugin/record-title', {
	usesContext: [ 'my-plugin/recordId' ],

	edit( { context } ) {
		return (
			<div>
				The record ID: { context['my-plugin/recordId'] }
			</div>
		);
	}
} );

PHP (render callback)

Context is available from the context property of the $block argument:
register_block_type( 'my-plugin/record-title', array(
	'render_callback' => function( $attributes, $content, $block ) {
		return 'The current record ID is: ' . $block->context['my-plugin/recordId'];
	}
) );
Block context is not available in the save function.

Complete example

This example creates a parent “record” block that provides a record ID to a child “record-title” block.

1. Create the block

npm init @wordpress/block --namespace my-plugin record
cd record

2. Define the provider block

Edit src/index.js:
import { registerBlockType } from '@wordpress/blocks';
import Edit from './edit';
import save from './save';

registerBlockType( 'my-plugin/record', {
	attributes: {
		recordId: {
			type: 'number'
		}
	},
	providesContext: {
		'my-plugin/recordId': 'recordId'
	},
	edit: Edit,
	save
} );

registerBlockType( 'my-plugin/record-title', {
	title: 'Record Title',
	category: 'widgets',
	usesContext: [ 'my-plugin/recordId' ],
	edit( { context } ) {
		return (
			<div>The record ID: { context['my-plugin/recordId'] }</div>
		);
	},
	save() {
		return null;
	}
} );

3. Create the edit component

Edit src/edit.js:
import { TextControl } from '@wordpress/components';
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';

export default function Edit( { attributes, setAttributes } ) {
	const { recordId } = attributes;
	const blockProps = useBlockProps();

	const TEMPLATE = [ [ 'my-plugin/record-title', {} ] ];

	return (
		<div { ...blockProps }>
			<TextControl
				label={ __( 'Record ID' ) }
				value={ recordId }
				onChange={ ( val ) => setAttributes( { recordId: Number( val ) } ) }
			/>
			<InnerBlocks template={ TEMPLATE } templateLock="all" />
		</div>
	);
}

4. Create the save function

Edit src/save.js:
import { useBlockProps } from '@wordpress/block-editor';

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	return (
		<div { ...blockProps }>
			<p>The record ID: { attributes.recordId }</p>
		</div>
	);
}

5. Test the block

When you type a number in the text box, the record-title block below displays the same number through context.

Context limitations

  • Context only supports values from block attributes
  • Context flows from ancestors to descendants only (one-way)
  • A block must explicitly declare context usage with usesContext
  • Context is not available in the save function

Use cases

Post context in templates

{
	"providesContext": {
		"postId": "postId",
		"postType": "postType"
	}
}

Query loop context

{
	"providesContext": {
		"queryId": "queryId",
		"query": "query"
	}
}

Custom context

{
	"attributes": {
		"backgroundColor": {
			"type": "string"
		},
		"textColor": {
			"type": "string"
		}
	},
	"providesContext": {
		"my-plugin/backgroundColor": "backgroundColor",
		"my-plugin/textColor": "textColor"
	}
}

Best practices

  • Use namespaced context names to avoid conflicts
  • Document available context for your blocks
  • Validate context values before using them
  • Provide fallback values when context is unavailable
  • Consider using InnerBlocks templates to ensure child blocks are present

Build docs developers (and LLMs) love