Comments (16)
I've been thinking a lot about implementing React-like context to Web Components and finally found an answer: why it should be React-like? Especially when React team itself decided to kill old-style context and create a new one.
In my opinion, React relies on components too much. They even replaced class inheritance with HOCs, trying to make classes looking like a function. It still doesn't work, because component have their own lifecycle, and it breaks the very idea of component = function
(I think React is great project changed everything in web development though).
Web Components are different. While React has its own compiler starting with React.render()
, Web Components don't have any external system to inject context as React does. But they don't have to do it, because we have a great platform-close tool to achieve any necessary context we need.
Just create a factory that consumes your store and produces connect
function, and it will work without any special context:
// createConnect.js
export const createConnector = store => (mapStateToProps, mapDispatchToProps) => baseElement => {
return class extends baseElement {
connectedCallback() {
this.__storeUnsubscribe = store.subscribe(() => this._stateChanged(store.getState()));
....
}
disconnectedCallback() {
if (this.__storeUnsubscribe) {
this.__storeUnsubscribe();
}
...
}
}
}
// connect.js
export default const connect = createConnect(createStore());
That's it. You don't need extra code to support complex system of context as it was in React.
Also I think it is very similar approach the new React context has. They use a function to create Provider and Consumer components that are exchanging value
property between each other. But we don't even need components to do it, everything is built-in.
from lit-element.
I created wc-context library that supports lit-element and skatejs as well vanilla web components
The API is still in flux
from lit-element.
This talk was posted to the Slack channel, and it might be of interest to this conversation as it came up in the context of Context Properties there: https://youtu.be/6o5zaKHedTE
from lit-element.
@Westbrook , Thanks, that is an amazing approach, Never occurred to me.
from lit-element.
This outside the scope of LitElement since it is focused on creating custom elements that work with normal DOM API's. We might reconsider adding an API like this in the future if there's enough interest and a concrete proposal.
We recommend looking at PWA Starter Kit for docs, examples, and best practices around using LitElement when making PWAs and other web apps. It uses Redux for state management.
from lit-element.
@Lodin More news on this topic,
With new CSS display type display: contents
.
You should not be afraid of extra DOM, since it does not affect layout.
It is slready supported by 83% of browsers
from lit-element.
@Lodin . Thank you for your response. But, one of the problems this issue addresses is testability and SSR. Problem with having static connect or store exported from the module makes it singleton, and harder to mock the store while testing and when doing SSR, especially when your app is a part of a larger app. This is issue also mentioned here.
I agree that having component in dom that does not have any visual footprint but just passes context can be confusing. probably this should not be a part of LitElement, more of a pwa-helpers. Iยดll do a PR with and idea I have and link it here soon.
from lit-element.
I have created a small lib called it wc-context, no packaging yet, its coming soon. In meantime want to get some feedback. There is a Redux exmaple in demo folder.
from lit-element.
@askbeka I still think the functions are better for it. I've got an idea to make them static and mimic new React.Context API completely.
const createContext = (default) => {
let ctx = default;
const provide = (newCtx) => {
ctx = newCtx;
}
const consume = () => {
if (!ctx) {
throw new Error('Context is not defined');
}
// do whatever you want from consumer
}
return {consume, provide};
}
export {
consume,
provide,
} = createContext();
What do you think about this approach?
from lit-element.
@Lodin , This approach is not much different from just using store in component, I am not saying that it is bad, it may be all you need if you have one team working on whole app and it is not big. But in other cases this apprach does not scale very well.
Imagine that you have an app that is being developed by multiple teams some of them can be offshore and they have their own source control. You can store context as a global object in page and make them use that, but then you have a problem if you need multiple stores in your app, and components should be used with different stores.
Good thing that we have DOM and custom element and events to solve that. I am experimenting with it, for now I am not really happy with API, but I will try to release alpha version soon to get more feedback.
I don't have much time unfortunately:(
from lit-element.
@askbeka Oh I see it now. Thanks, talking with you was really useful. Waiting for your context lib!
from lit-element.
Thanks for @Westbrook mentioning Justin Fagnani's presentation, @askbeka's demo code and @blikblum's library.
from lit-element.
@rikakomoe you are welcome. Thanks for reminding. Almost forgot about this issue.
I couldn't find time to update on my final solution.
But, since then I have contributed context implementation for haunted.
Which implements reacts's hooks pattern with webcomponents.
There is also recent ongoing attempt to make react-redux work you can track here
from lit-element.
@askbeka The official guide requires a constant existing store before defining the element. The issue is, besides it is not tidy enough though, I am not building a website but a component, if the user creates more than one instance, all of them need their independent state. So I was looking for a declarative method to inject this store into children components, for convenience, without passing down the store over and over. React provides this dependency injection feature as its context while lit-element doesn't yet.
I'm interested about your final solution, if there were any updates/improvements against the solution I've seen so far.
from lit-element.
@rikakomoe, you can also try my context approach that implemented in the @corpuscule/context library. It allows avoiding unnecessary HTML elements whose only purpose is to serve as a provider. With this library, you can make your root component a theme provider, a redux provider, a router provider, etc. at the same time without creating expensive HTML elements and increase nesting. It works with any implementation of web components.
The library is based on decorators, so you will need Babel to transpile your components while the decorator proposal is in development. Corpuscule project provides solution for it as well.
BTW, the redux bindings (based on the context library) are also there: @corpuscule/redux. It also works with any web component library as well as vanilla web components.
from lit-element.
@Lodin Thanks!
from lit-element.
Related Issues (20)
- Typescript error on latest build HOT 1
- mixins don't work when using ESNext in tsconfig to compile HOT 1
- Error throw when accessing queryAssignedNodes getter (No version >2.4.0) HOT 1
- Support for contexts? HOT 2
- Persistance? HOT 5
- idempotent/soft customElement decorator HOT 1
- state() is shown as deprecated in LitElement 2.5 HOT 1
- Should not be necessary to copy TemplateResult
- jsdelivr/+esm: [object Object] HOT 1
- Nested components, slot and text styling HOT 1
- Git tags are not in sync with npm tags HOT 2
- No release major/minor branches available for reference. HOT 2
- Move tests and benchmarks to GitHub Actions
- Accessibility => lit-element + Google Chrome Screen Reader Extension => UI Design is Changed HOT 3
- Property does not re-render when fired from custom event HOT 4
- Add a way to know when rendering of an element, and ALL its sub-elements, is finished HOT 3
- Litelement Boolean property returns undefined in when not set HOT 6
- Forward Compatibility With Lit 2 misleading HOT 2
- Starter projects missing in getting started documentation HOT 1
- How do you get the actual click event target? HOT 4
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 lit-element.