Comments (6)
It is a very interesting case :) How to start... Hybrids uses prototype mechanism to define properties, and they are getter/settter properties. In JavaScript when you set the value to those properties, instead of creating own property (on the top object instance), the set method from the prototype is called. It means that the instance still does not have own property... Now, let's see your code. In your example you are passing host properties into the React component using spread operator - by the definition, it only passes "own" properties, so it should not work at all. However, why does it work in Angular? It should not work too, but if it really works it means that angular has a problem and not use the prototype (proper assertion, using '=' operator), but set property by Object.defineProperty()
method and does it on the instance (which would stupid by the way).
The second problem of your WC generator is that you don't define input properties - so hybrids will not re-render your component when they will change... Hm.. It might be a answer why it works in angular, but not in Vue - they might pass properties at a different moment in time - the first before appending to the DOM, and the latter after. Hybrids renders your template for the first time with (Angular) or without (Vue) properly set properties.
How you can fix it? Your React components should inform what kind of input properties they use. If you don't care about types, you can define them all with undefined
value in hybrids component definition, but you have to do this. Then, if you will have a list of input properties, you should explicitly pass them to React component rather than using the spread operator. I think static propTypes can help you with that.
// Grab all of the momentum-ui react components
const webComponents = Object.keys(Components).reduce((acc, key) => {
// Grab the react component whenever being invoked
const Component = Components[key];
const inputProps = Object.keys(Component.propTypes);
const component = {
render: render(() => {
return (host, target) => {
const props = inputProps.reduce((acc, key) => {
acc[key] = host[key];
return acc;
});
// Render the component with the given properties
ReactDOM.render(<Component {...props} />, target);
}
}, { shadowRoot: false }) // No to Shadow DOM
};
// Define input props of the React component
inputProps.forEach((key) => {
component[key] = undefined;
});
// Convert the PascalCase string with lowercase string plus dashes in between
const name = `web-comp${key.replace(/[A-Z]/g, m => "-" + m.toLowerCase())}`;
acc[name] = component;
return acc;
});
define(webComponents);
from hybrids.
@smalluban will do. Some react components from that third party library are missing prop-types. Iām trying to figure out why, but I was planning to just make this work with the other components. Will update you ASAP.
from hybrids.
I'm assuming using reactDom.render many many times is not the best approach for a large scale application.
If you plan to build "a large scale application" and use a lot of react components, it might not be the best idea to wrap them all in web components ;) The main goal of wrapping React in web components is to let users from other frameworks use particular components with a standardized way without need to use React directly.
However, I always thought that calling ReactDOM.render
after initial load will work the same as you would call forceUpdate()
inside of the component. As we know, that props have changed (because of how hybrids cache works) it is the same as passing new props to the component inside of the React tree. It should not have a performance impact on your application.
There is an issue in React repo about it, which is signed as a bug, and what I read it's solved: facebook/react#12700
from hybrids.
@akoushke Let me know if my solution works. If you don't have any other problem with the case please close the issue.
from hybrids.
I'm going to close this right now. Will update you if there was any more issues. thanks again.
from hybrids.
I did have another question in terms of using reactDom.render
.
I'm assuming using reactDom.render
many many times is not a best approach for a large scale application. However, I found that's the only way to wrap a react component into a web component.
Obviously I'm talking about this line of code here:
ReactDOM.render(<Component {...props} />, target);
Is there a way to come up with a precompiled html code without given properties? maybe I can use that html template into my web component definition and embed the props later in the runtime? That way I don't have to call ReactDom.render
for each component. I just return the html code with given embedded properties. does this makes sense? I know that ReactDomServer
offers html initial from a given react component. However, you will need to pass a react element first which requires props and/or children. any suggestions? I'm all ears!!!! thanks <3
from hybrids.
Related Issues (20)
- AsyncIterator HOT 2
- Initializing object properties with `undefined` no longer accepted in v8.0.0 HOT 4
- Feature Request: Custom Elements Manifest Analyzer HOT 1
- Class attribute mix-in _on_ the web-component HOT 12
- Extension for FLIP / Miotion Animations in planning? HOT 10
- Timing of connect during instantiation HOT 13
- Rendering components without the ShadowDOM? HOT 1
- Working with Chart.js HOT 1
- `class` attribute changes rendering in v8.1.7 HOT 4
- render function mutating host property breaks rendering in v8.1.6 HOT 5
- Properties assigned undefined when accessing them for the first time HOT 1
- Why don't store models leverage property descriptors too? HOT 7
- Storage-first/storage-only option for [store.connect] HOT 10
- React integration - Error while unmounting the component HOT 2
- Try render a table but encounter a problem HOT 3
- about destructured host parameter in render function HOT 2
- I'm trying to load a model on button click. Component does not update after loading model HOT 5
- A storage without an identifier loads data even before assigning an identifier HOT 2
- Starter / template repository ? HOT 2
- How do I tap into `connected` / `disconnected` lifecycle methods ? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
š Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ššš
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ā¤ļø Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hybrids.