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

Try: Preact #2734

Closed
wants to merge 5 commits into from
Closed

Try: Preact #2734

wants to merge 5 commits into from

Conversation

mtias
Copy link
Member

@mtias mtias commented Sep 15, 2017

(Converting to pull request for better visibility.)


This explores using preact as the primitive powering the rendering mechanism of Gutenberg.

Known issues:

  • Avoid using element fragments in blocks (related to consistent block edit declarations).
  • Fix react-click-outside dependency.
  • Block focus issues.
  • Popover ref allocation with slot/fill.
  • componentDidCatch alternative. Support for componentDidCatch preactjs/preact#799

youknowriad and others added 5 commits September 8, 2017 12:30
The two differences are:

- Uses el.getDOMNode instead of ReactDOM.findDOMNode.

- Doesn't inline the `ref` function within `render`, but binds a proper
  method to the instance.
@mtias mtias added the Framework Issues related to broader framework topics, especially as it relates to javascript label Sep 15, 2017
@adamsilverstein
Copy link
Member

@mtias Nice to see this PR, I've been playing around with React on some projects and impressed with its lightweight, performant approach and overall philosophy.

I gave the PR a test and it looks like some issues have been worked out, but I had trouble getting past issues with the popover - any hints on how to work on fixing that? I didn't understand your reference to "Popover ref allocation with slot/fill.".

In regard to componentDidCatch, this is something Preact itself will hopefully add: preactjs/preact#799

@mcsf
Copy link
Contributor

mcsf commented Sep 15, 2017

I gave the PR a test and it looks like some issues have been worked out, but I had trouble getting past issues with the popover - any hints on how to work on fixing that? I didn't understand your reference to "Popover ref allocation with slot/fill.".

@adamsilverstein, I had a go at this yesterday. Haven't fixed it yet, but the gist seems to be that slight differences in the render lifecycle between React and Preact mean that the refs for the elements within the Fill wrapper aren't ready when Popover's componentDidUpdate gets called. Hence, this.nodes a value for 'anchor' but not for 'popover' or 'content'. Deferring certain calls yields some improvements, but they're inconsistent and feel fragile.

@mtias
Copy link
Member Author

mtias commented Sep 15, 2017

In regard to componentDidCatch, this is something Preact itself will hopefully add.

Yes, forgot to reference the PR over there. :)

@adamsilverstein
Copy link
Member

but the gist seems to be that slight differences in the render lifecycle between React and Preact mean that the refs for the elements within the Fill wrapper aren't ready when Popover's componentDidUpdate gets called

Fun! Thats a good lead, I'll see if I can figure out why that is happening - that also explains why the popup sort of works the second time you try it.

id={ id + '-toolbar' }
ref={ ref => this.ref = ref }
className="freeform-toolbar"
/>,
Copy link
Member

Choose a reason for hiding this comment

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

Comma here will be output as a string.

return [
controls,
<div key="audio">
return (
Copy link
Member

Choose a reason for hiding this comment

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

While it means we can't treat edit as a component proper (i.e. assigned as class extends Component, which we don't support well for save anyways), I think we could still potentially support array returns by wrapping the return value from the function from the block rendering handler. That or if we identify common characteristics of a block "container", we could create a wrapper component like <Block> for the block implementer to use.

@@ -6,7 +6,7 @@ import { pick, noop } from 'lodash';
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { Component, Children } from '@wordpress/element';
Copy link
Member

Choose a reason for hiding this comment

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

Can we avoid the Children utility and instead leverage the fact that children is an array in Preact, i.e.

// Before:
Children.only( this.props.children );

// After:
this.props.children[ 0 ];

I think it would be good if we avoid Children altogether.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's the exact same thing, the inner implementation is the same, but I can see that this enables to drop preact-compat at some moment.

return [
focus && (
<BlockControls key="controls">
return <div>
Copy link
Member

Choose a reason for hiding this comment

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

For consistency, should this be parenthesis-wrapped?

@@ -1,27 +1,22 @@
/**
* External dependencies
*/
import { noop } from 'lodash';
import { Slot } from 'react-slot-fill';

/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';

class PopoverProvider extends Component {
Copy link
Member

Choose a reason for hiding this comment

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

Without context, this doesn't need to be a component class. I also don't think it needs to be a provider in the sense of having children, but rather a slot rendered directly in the layout component. Something like: <PopoverSlot />.

react: 'preact-compat',
'react-dom': 'preact-compat',
// Not necessary unless you consume a module using `createClass`
'create-react-class': 'preact-compat/lib/create-react-class',
Copy link
Member

Choose a reason for hiding this comment

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

Is this needed for the components we're using?

Copy link
Contributor

@youknowriad youknowriad Sep 17, 2017

Choose a reason for hiding this comment

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

it might be needed for the react libraries we're using but yeah we could try to remove it and see

@@ -2,7 +2,7 @@
* External dependencies
*/
import { createElement, Component, cloneElement, Children } from 'react';
import { render, findDOMNode, unstable_createPortal } from 'react-dom'; // eslint-disable-line camelcase
import { render, findDOMNode } from 'react-dom'; // eslint-disable-line camelcase
import { renderToStaticMarkup } from 'react-dom/server';
Copy link
Member

Choose a reason for hiding this comment

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

We should replace this with preact-render-to-string

https://github.com/developit/preact-render-to-string

@gziolo
Copy link
Member

gziolo commented Jan 31, 2018

This turned out to be very useful when exploring if we can replace React with Preact. It is no longer up to date so I'm closing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Framework Issues related to broader framework topics, especially as it relates to javascript
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants