providesContext and usesContext – Block API

Nick Diego shared this code example on helping out the OP on the GitHub issues. The use case by itself would be fascinating, but I just want to learn about this particular code.

Nick shared it in the WordPress Slack #outreach channel to help a user with his code. You can read the full conversation here (you need a wp.org account and a slack account, though)

My new favorite AI tool is Perplexity to use as a learning tool. Below you find the answer to the prompt and to follow-up questions.

“Can you explain this code to a newbie?”

add_filter( 'block_type_metadata',  function( $metadata ) {
	
	if ( isset( $metadata['name'] ) && 'core/list-item' === $metadata['name'] ) {
		$metadata['usesContext']   ??= [];
		$metadata['usesContext'][] = 'useIcon';
		$metadata['usesContext'][] = 'icon';
	}

	if ( isset( $metadata['name'] ) && 'core/list' === $metadata['name'] ) {
		$metadata['attributes']['useIcon'] = array(
			'type'    => 'boolean',
			'default' => 'false'
		);
		$metadata['attributes']['icon'] = array(
			'type'    => 'string',
			'default' => 'test' // Just for testing.
		);

		$metadata['providesContext']            ??= [];
		$metadata['providesContext']['useIcon'] = 'useIcon';
		$metadata['providesContext']['icon']    = 'icon';
	}

	return $metadata;
} );

add_action( 'render_block_core/list-item', function( $block_content, $block, $instance ) {
    
    if ( ! isset( $instance->context ) ) {
        return $block_content;
    }

    $context = $instance->context;
    $useIcon = $context['useIcon'] ??= false;
    $icon    = $context['icon']    ??= '';

    if ( $useIcon && $icon ) {
        // Do whatever you want here...
        return $block_content . ' ' . $context['icon'];
    } 

    return $block_content;
}, 10, 3 );

The Answer:

This appears to be WordPress-related PHP code that modifies the behavior of certain blocks. Let’s break it down:

First Function: Modifying Block Metadata

php
add_filter( 'block_type_metadata', function( $metadata ) { // ... (code inside) });


This adds a filter to modify the metadata of block types. It’s an anonymous function that takes $metadata as an argument. Inside this function:

  1. For the ‘core/list-item’ block: It adds ‘useIcon’ and ‘icon’ to the usesContext array.
  2. For the ‘core/list’ block: It adds two new attributes: ‘useIcon’ (boolean) and ‘icon’ (string).
  3. It also adds these to the providesContext array.


Second Function: Modifying Block Rendering

php
add_action( 'render_block_core/list-item', function( $block_content, $block, $instance ) { // ... (code inside) }, 10, 3 );

This adds an action to modify how the ‘core/list-item’ block is rendered. It’s another anonymous function that takes three parameters. Inside this function:

  • It checks if the block instance has a context.
  • If it does, it retrieves ‘useIcon’ and ‘icon’ from the context.
  • If ‘useIcon’ is true and ‘icon’ is not empty, it appends the icon to the block content.

Key PHP Features

  1. Used:??=: This is the null coalescing assignment operator. It assigns the right side only if the left side is null or doesn’t exist.
  2. Array manipulation: Adding elements to arrays using [] notation.
  3. Associative arrays: Using key-value pairs like 'type' => 'boolean'.
  4. Short-circuit evaluation: $useIcon && $icon checks if both are truthy.


This code essentially adds icon functionality to list and list item blocks, allowing users to specify whether to use an icon and what icon to use. It’s a way to extend the core WordPress blocks with custom functionality.

So far, the explanation. A Follow-up question Perplexity suggested:

What is the purpose of the usesContext and providesContext arrays in the metadata

The usesContext and providesContext arrays in the block metadata serve important purposes for managing data flow between WordPress blocks:

  1. usesContext:
    • This array specifies which context values a block wants to consume from its parent blocks.
    • It allows a child block to access data provided by its ancestors without explicitly passing props through every level of the block hierarchy.
    • In the given code, the ‘core/list-item’ block is set up to use ‘useIcon’ and ‘icon’ context values:
    php$metadata['usesContext'][] = 'useIcon'; $metadata['usesContext'][] = 'icon';
  2. providesContext:
    • This object defines the context values that a block makes available to its descendant blocks.
    • It maps context names to the block’s own attributes, allowing child blocks to access these values.
    • In the code, the ‘core/list’ block is set up to provide ‘useIcon’ and ‘icon’ context values:
    php$metadata['providesContext']['useIcon'] = 'useIcon'; $metadata['providesContext']['icon'] = 'icon';

The purpose of using these arrays is to:

  1. Enable data sharing between parent and child blocks without prop drilling.
  2. Allow blocks to be more flexible and reusable by consuming context from their ancestors.
  3. Provide a way for parent blocks to influence the behavior or appearance of their children without tightly coupling them.

In this specific case, the code is setting up a system where a list block can provide icon-related information to its list item children, allowing for customization of list item appearances based on the parent list’s settings.

The next question, I found particular interesting:

How does block context differ from React Context

Block context in WordPress and React Context share similar concepts, but they have some key differences in their implementation and use cases:

  1. Scope and Purpose:
    • Block context is specific to WordPress blocks and is designed to share data between parent and child blocks in the block editor.
    • React Context is a more general-purpose feature for passing data through the component tree without explicitly passing props at every level.
  2. Implementation:
    • Block context is implemented using WordPress-specific APIs and is defined in the block’s JSON configuration.
    • React Context uses the React.createContext() API and Provider/Consumer components or the useContext hook.
  3. Data Flow:
    • Block context only flows downward from parent blocks to their descendants.
    • React Context can be updated and consumed at any level of the component tree.
  4. Availability:
    • Block context is available in both JavaScript (client-side) and PHP (server-side) implementations of blocks.
    • React Context is only available in JavaScript and is tied to the React library.
  5. Configuration:
    • Block context is configured using providesContext and usesContext properties in the block’s JSON file.
    • React Context is set up programmatically in JavaScript code.
  6. Use Cases:
    • Block context is primarily used for sharing data between WordPress blocks, such as passing a post ID from a parent block to child blocks.
    • React Context is used for broader application-wide state management and theming in React applications.
  7. Performance Considerations:
    • Block context is optimized for the WordPress block editor environment.
    • React Context can trigger re-renders in all consuming components when the context value changes, which may require additional optimization in large applications.
  8. Namespace:
    • Block context often uses namespaced keys to avoid conflicts between plugins or with WordPress core.
    • React Context doesn’t have a built-in namespacing system, though developers can implement their own conventions.

While both mechanisms serve the purpose of sharing data without prop drilling, block context is a more specialized tool designed for the WordPress block ecosystem, whereas React Context is a more flexible and general-purpose feature of the React library.



Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.