Jetpack: Blocks: broken with WP 5.3

Created on 22 Jun 2020  Â·  14Comments  Â·  Source: Automattic/jetpack

16107 may have broken our blocks in older versions of WordPress.

If you test a WordPress 5.3.4 site with Jetpack Master today, you'll run into the following error when trying to insert an Image Compare block for example:

TypeError: Object(...) is not a function
    at eval (cover-media-placeholder.js:75)

image

@retrofox Do you think you could take a look?

Gutenberg [Pri] BLOCKER [Type] Bug

Most helpful comment

The reason useBlockEditContext doesn't break the VideoPress block is that its use sits behind an isSimpleSite check, while for the cover block it gets called before that.

All 14 comments

Assigning @marekhrabe who beat me to that report here:
https://github.com/Automattic/jetpack/pull/16069#issuecomment-647611158

I'm working on a fix. The most straightforward path for me was to introduce a new HOC in Jetpack that deals with the compatibility differences. I've created withBlockName, since that is the only piece of the context we use.

/**
 * WordPress dependencies
 */
import { useBlockEditContext, withBlockEditContext } from '@wordpress/block-editor';
import { createHigherOrderComponent } from '@wordpress/compose';

const withBlockName = createHigherOrderComponent(
    ( WrappedComponent ) => ( props ) => {
        // Use hook available in WP 5.4 and newer.
        if ( typeof useBlockEditContext === 'function' ) {
            const { name } = useBlockEditContext();
            return <WrappedComponent { ...props } blockName={ name } />;
        }
        // Fallback to HOC for versions before 5.4.
        return withBlockEditContext( ( { name } ) => ( { blockName: name } ) )(
            WrappedComponent
        );
    },
    'withBlockName'
);

export default withBlockName;

However, I have just hit a roadblock :( While useBlockEditContext is exported from the block editor package, the predecesor withBlockEditContext was never exported and only used internally in Gutenberg. That means my code above won't work. Investigating more…

Both versions are exported from context.js, which means they could be imported and used in the Gutenberg codebase, however, only the newer useBlockEditContext is reexported and available in the API plugins can use.

Context definition in WP 5.3:

https://github.com/WordPress/gutenberg/blob/wp/5.3/packages/block-editor/src/components/block-edit/context.js

Context definition in WP 5.4:

https://github.com/WordPress/gutenberg/blob/wp/5.4/packages/block-editor/src/components/block-edit/context.js

Public export in 5.3:

https://github.com/WordPress/gutenberg/blob/wp/5.3/packages/block-editor/src/components/block-edit/index.js#L15

Public export in 5.4:

https://github.com/WordPress/gutenberg/blob/wp/5.4/packages/block-editor/src/components/block-edit/index.js#L15

@retrofox Do you think you could take a look?

yes, of course

From what I found so far, I don't think there is a suitable alternative for useBlockEditContext before WP 5.4. Since we are only using it in different places where we alter the MediaPlaceholder using the editor.MediaPlaceholder.

I've tried inspecting props of the MediaPlaceholder to see if we can determine the block name some other way. In WP 5.3, the className prop seems to be available and it contains the block name (not exactly but can be used for the same check). However, the className stopped working in newer Gutenberg versions so it needs further confirmation.

Reference to where className was previously used but removed: https://github.com/Automattic/jetpack/pull/15906

Using className checks instead of useBlockEditContext will likely fix the incompatibility with both WP 5.3 and 5.4. However, that's pure core. If you also have Gutenberg 8.1 and newer, className checks are no longer possible. However, Gutenberg 8.1 already has useBlockEditContext as seen in:

https://github.com/WordPress/gutenberg/blob/release/8.1/packages/block-editor/src/components/block-edit/context.js

Next steps

We need to find all usages of useBlockEditContext in editor.MediaPlaceholder calls and implement a logic that checks both the className and useBlockEditContext, while having guards in place that in no situation we use useBlockEditContext without it being available.

If this way doesn't work, I'm afraid we need to remove those features or only make them available if we detect the hook is available, as there seems no other API capable of checking what we need.

Using className checks instead of useBlockEditContext will likely fix the incompatibility with both WP 5.3 and 5.4. However, that's pure core. If you also have Gutenberg 8.1 and newer, className checks are no longer possible. However, Gutenberg 8.1 already has useBlockEditContext as seen in:

I think we shouldn't rely on this the className attribute at all. It makes the implementation unstable.

Next steps

We need to find all usages of useBlockEditContext in editor.MediaPlaceholder calls and implement a logic that checks both the className and useBlockEditContext, while having guards in place that in no situation we use useBlockEditContext without it being available.

We should consider getting rid of the hook too. Guessing it's possible using different filters. Trying it on https://github.com/Automattic/jetpack/pull/16171. This PR has many changes to respect what is the primary branch.

If this way doesn't work, I'm afraid we need to remove those features or only make them available if we detect the hook is available, as there seems no other API capable of checking what we need.

🤞

I think using className would be a valid fallback where the hook is not available. I consider it stable enough because className will only be used with old WP/Gutenberg versions and the code of those is known and will never update.

If you find a completely different way, that would be the best, otherwise I think we should use className or completely disable those features when we know the hook is not available

yes, fair enough. Not sure if it works. Going to spend some minutes on this.

I think we should use className or completely disable those features when we know the hook is not available

I'm leaning towards disabling the notice when useBlockEditContext is not available. The feature works only for simple sites anyway, where useBlockEditContext is available, so disabling it for older WP versions should not change anything.

@jeherve How would you feel about that?

The reason useBlockEditContext doesn't break the VideoPress block is that its use sits behind an isSimpleSite check, while for the cover block it gets called before that.

I implemented a solution removing the useBlockEditContext using a different filter to extend the EditoBlock function of the cover block. Basically, it picks up the block name and passes it to the HOC to finally provide this value to the media cover context.

Picking up the name...

export default ( settings, name ) => {
    if ( ! isUpgradable( name ) ) {
        return settings;
    }

    return {
        ...settings,
        edit: JetpackCoverBlockEdit( name )( settings.edit ),
    };
};

... passing to the HOC

const JetpackCoverBlockEdit = ( blockName ) => createHigherOrderComponent(
    ( CoverBlockEdit ) => props => {
        // ...
        return (
            // ...
        );
    },
    'JetpackCoverBlockEdit'
)

Providing block name:

return (
    <Fragment>
        <CoverMediaProvider
            onFilesUpload={ handleFilesPreUpload }
            blockName={ blockName }
        >
        // ...

The whole implementation is https://github.com/Automattic/jetpack/pull/16240.

Also, @obenland did another approach to tackle the same issue. It adds the filter only if the cover block _is upgradable_. Here the PR https://github.com/Automattic/jetpack/pull/16241.
Both branches of these PRs have been branched off from update/cover-get-allowed-mime-types https://github.com/Automattic/jetpack/pull/16171

I would personally vote for the upgradable check approach, for a few reasons:

  • It feels a bit simpler and quicker to parse and understand for someone new to the codebase.
  • Since WordPress 5.5 will be released this summer, and we'll then have access to useBlockEditContext since we won't support WP 5.3 anymore, I feel comfortable going with that approach.
  • If in the future we decide to start using such nudges outside of simple sites, by then we'll most likely already have access to useBlockEditContext because of the above.

What do y'all think?

@jeherve I agree. I've voiced something similar elsewhere https://github.com/Automattic/jetpack/pull/16241#issuecomment-648712233

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jeherve picture jeherve  Â·  3Comments

ockham picture ockham  Â·  3Comments

beaulebens picture beaulebens  Â·  3Comments

Viper007Bond picture Viper007Bond  Â·  3Comments

crunnells picture crunnells  Â·  3Comments