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

Equivalent of mountComponent in Fiber? #9192

Closed
markbrocato opened this issue Mar 16, 2017 · 20 comments
Closed

Equivalent of mountComponent in Fiber? #9192

markbrocato opened this issue Mar 16, 2017 · 20 comments

Comments

@markbrocato
Copy link

In extjs-reactor we use some react internal methods like mountComponent, unmountComponent, and receiveComponent, as well as the ReactMultiChild mixin to defer rendering to Ext JS. This interface was very helpful for anyone looking to make generic JS component libraries work in React (as opposed to those built specifically for React).

Is there an equivalent/alternative way to control the mounting of a component in the new Fiber architecture?

If it helps, here is the code that references the React internal methods:

https://github.com/sencha/extjs-reactor/blob/master/packages/reactor/src/ExtJSComponent.js

@gaearon
Copy link
Collaborator

gaearon commented Mar 16, 2017

There is no support for using React like this in Fiber, no. Please refer to my replies in #8358.

You can create a custom renderer with Fiber if you want to be in full control, but this would mean that you wouldn’t be using ReactDOM at all. You can look at ReactARTFiber for an example of such renderer. We don't offer a public API to create one in userland yet, but we intend to expose one in the coming months.

Hope this helps!

@gaearon gaearon closed this as completed Mar 16, 2017
@markbrocato
Copy link
Author

Thank you. I did look at ReactARTFiber. I don't think I should go that route because I'd hate to lose all of the good functionality of ReactDOM.

Generally the way to integrate generic JS components has been to render a target div which is passed along to the generic component's constructor in componentDidMount. All I really need is a way around rendering this target div for each component, as it creates unnecessary dom elements that break the ExtJS layout system. Is there any way around that? I can even live with rendering the target div for only the root component in an Ext JS component hierarchy. It seems like I'm so close and my original approach may have even been too complicated.

@gaearon
Copy link
Collaborator

gaearon commented Mar 16, 2017

So you want to create DOM nodes via a non-React library, but make those DOM nodes part of React output?

@markbrocato
Copy link
Author

Yes, exactly! I think the ability to do that coupled with the existing public lifecycle methods gives me all I need.

@gaearon
Copy link
Collaborator

gaearon commented Mar 16, 2017

Do you allow putting non-ExtJS components into ExtJS components?

@markbrocato
Copy link
Author

markbrocato commented Mar 16, 2017

Yes. Sometimes we wrap them in a base Ext.Component instance, but with the current implementation something like <Container layout="hbox"><div>left</div><div>right</div></Container> is totally doable (Container being an Ext JS component class).

@gaearon
Copy link
Collaborator

gaearon commented Mar 16, 2017

I do think that custom renderer like ReactARTFiber is the way to go here. You can use it together with react-dom fine. It means some code duplication but that’s the tradeoff.

@markbrocato
Copy link
Author

I'm trying the renderer route as you suggested and it seems promising.

I'm struggling with the case where there are html elements inside an Ext JS component. For example:

<Component>
  <div>foo</div>
</Component>

When implementing ReactFiberReconciler, Is there some way I can have ReactDOM render and update the html elements so I only need to worry about handling Ext JS components? I wouldn't want to recreate all of the functionality of ReactDOM.

@gaearon
Copy link
Collaborator

gaearon commented Mar 17, 2017

I think you could have Container be a composite component that calls ReactDOM.unstable_renderIntoContainer in componentDidMount and DidUpdate. Does this help?

We plan to simplify this with cross-renderer portals but they're not implemented yet.

We plan to provide

@markbrocato
Copy link
Author

After fully exploring custom rendering, I think I've got something that preserves all of the functionality of the old extjs-reactor implementation with only minor changes to the API.

You can see my new implementation here:

https://github.com/sencha/extjs-reactor/blob/fiber/packages/reactor-fiber/src/ExtReactProvider.js

My general approach was to handle Ext JS components directly and to use ReactDOM.render() for any child HTML elements. This seems to work well!

There are only two side effects:

  1. Developers need to add a new component called ExtReactProvider at the root of anywhere they want to use Ext JS components. This is not ideal, but acceptable given that other component libraries such as material-ui require something similar.

2.) The react chrome tools don't seem to render the component tree correctly. Children of ExtReactProvider are listed at the root of the tree. Do you think the chrome tools just need to be updated to support fiber? Or is there something else I need to do when rendering custom elements?

Would you mind taking a quick look at my code and letting me know if this is in line with the public API you intend to offer for custom rendering? Am I doing anything that is likely to break in the near future?

Overall I feel like the ReactFiberReconciler API is a lot easier to understand than the old APIs. Kudos to you guys! I'm guessing we are one of the first third parties to use this API? I'd love the chance to help guide the direction of this API in the future and offer help/feedback where it is needed.

@gaearon
Copy link
Collaborator

gaearon commented Mar 20, 2017

2.) The react chrome tools don't seem to render the component tree correctly. Children of ExtReactProvider are listed at the root of the tree. Do you think the chrome tools just need to be updated to support fiber? Or is there something else I need to do when rendering custom elements?

This is because we don't have support for cross-renderer portals. The idea is that in the future, instead of calling updateContainer() in lifecycle hooks, you would use the portal API in the render method. Something like:

render() {
  return createPortal(
    this.props.children,
    this._mountNode,
    ExtJSRenderer
  ); 
}

This cross-renderer support is not currently implemented although we’d love to see contributions in that space. I’m not sure how hard that would be.

Kudos to you guys! I'm guessing we are one of the first third parties to use this API? I'd love the chance to help guide the direction of this API in the future and offer help/feedback where it is needed.

Yes! 😄

@gaearon
Copy link
Collaborator

gaearon commented Mar 20, 2017

Am I doing anything that is likely to break in the near future?

I think the code makes sense! I would just note that ReactFiberReconciler will not be available inside react-dom itself—we’ll likely offer it separately somehow in React 16 or soon after it’s out. We haven’t worked out the details of exposing it yet.

@markbrocato
Copy link
Author

I see that ReactFiberReconciler and ReactDOMFrameScheduling are no longer exported by react-dom as of alpha.7. Is there any way I can get to those currently? Will you be able to get a public API exposed for those in an upcoming prerelease of React 16? I'd love to be able to stay on top of testing future prereleases so we can guarantee compatibility when React 16 lands.

@gaearon
Copy link
Collaborator

gaearon commented Apr 7, 2017

There’s currently no easy way except for forking the repo but we plan to provide something before cutting 16.

@markbrocato
Copy link
Author

Forking the repo is ok for now. FWIW, all I did to get things working again was export those two classes as members of react-dom:

https://github.com/markbrocato/react/blob/master/src/renderers/dom/fiber/ReactDOMFiber.js#L416

Maybe in the end you'll end up publishing src/shared/fiber as an additional "react-fiber" package so that multiple renderers could reuse the same fiber internals?

Please don't hesitate to reach out if you need my help or feedback in bringing this API public.

@gaearon
Copy link
Collaborator

gaearon commented Apr 7, 2017

Maybe in the end you'll end up publishing src/shared/fiber as an additional "react-fiber" package so that multiple renderers could reuse the same fiber internals?

Something like this, or potentially a build tool for renderers that reuses our build toolchain.

@markbrocato
Copy link
Author

Hey @gaearon, I notice React 16 is now in beta. Congrats! Just checking in to see if there has been any movement on this. Does the beta provide a way for third parties to create renderers?

@gaearon
Copy link
Collaborator

gaearon commented Jul 27, 2017

No, this is still on our list before the final release.

@markbrocato
Copy link
Author

I see that React 16 has been released. Have you come to a resolution on how to support third party renderers?

@iamdustan
Copy link
Contributor

@markbrocato #9103

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants