Comments (15)
I tried to use invalidate
method after the request, but still no success
from hybrids.
I removed the http request and put a mocked value, and it worked. Looks like promises doesn't work as it should
from hybrids.
Please, look at the Promises section in the documentation. There is an example, how to use async data in templates and more general in hybrids.
connect
method is not a place to do calls. You should use getter to do that. Async request is only called again if cache invalidates (when related properties of your getter change).
Your ongs
property should be defined like this:
const ongsList = {
ongs: () => getOngs(),
render: ({ ongs }) => html`
<div>
${html.resolve(
ongs.then(ongs => ongs.map(ong => html`<li>${ong.name}</li>`))
)}
</div>
`,
};
Pay attension to html.resolve
method and how your ongs are iterated - a map function should return template.
Your ongs
property is not related to any other property, so getOngs()
is called only once, when render
requires it.
from hybrids.
Thanks for the help
I've changed the code, but I'm getting "template is not a function"
const resolveOngsPromise = ongsPromise => html`
${html.resolve(
ongsPromise.then(ongs => ongs.map(ong => html`
<li>
<div class="collapsible-header">${ong.name} - ${ong.taskTitle}</div>
<div class="collapsible-body"><span>Lorem ipsum</span></div>
</li>
`)),
)}
`;
const ongsListRender = ({ ongs }) => html`
${materializeStyle}
<h1>Help My.ONG</h1>
<ul class="collapsible">
${resolveOngsPromise(ongs)}
</ul>
`;
const ongsList = {
ongs: getOngs(),
render: ongsListRender,
};
from hybrids.
I tried removing the html
from resolveOngsPromise
and still doesn't work
const resolveOngsPromise = ongsPromise => html.resolve(
ongsPromise.then(ongs => ongs.map(ong => html`
<li>
<div class="collapsible-header">${ong.name} - ${ong.taskTitle}</div>
<div class="collapsible-body"><span>Lorem ipsum</span></div>
</li>
`)),
);
from hybrids.
You can't do this:
const ongsList = {
ongs: getOngs(),
render: ongsListRender,
};
This is the definition of your properties, not values... It should be:
const ongsList = {
ongs: () => getOngs(), // <-- it has to be a function, not a promise value
render: ongsListRender,
};
from hybrids.
Sorry for the silly mistake. But even after changing it I'm getting the same error
const resolveOngsPromise = ongsPromise => html`
${html.resolve(
ongsPromise.then(ongs => ongs.map(ong => html`
<li>
<div class="collapsible-header">${ong.name} - ${ong.taskTitle}</div>
<div class="collapsible-body"><span>Lorem ipsum</span></div>
</li>
`)),
)}
`;
const ongsListRender = ({ ongs }) => html`
${materializeStyle}
<h1>Help My.ONG</h1>
<ul class="collapsible">
${resolveOngsPromise(ongs)}
</ul>
`;
const ongsList = {
ongs: () => getOngs(),
render: ongsListRender,
};
// getOngs
export const getOngs = async () => {
const data = await fetch(`${url}/ongs`);
const jsonData = await data.json();
return jsonData;
};
from hybrids.
Even after changing getOngs implementation to:
export const getOngs = () => {
return fetch(`${url}/ongs`)
.then((res) => res.json());
};
The error stays
from hybrids.
This was my mistake. The first .then()
should return template. By the way, you have one additional wrapper over the result.
const resolveOngsPromise = ongsPromise => html.resolve(
ongsPromise.then(ongs => html`
${ongs.map(ong => html`
<li>
<div class="collapsible-header">${ong.name} - ${ong.taskTitle}</div>
<div class="collapsible-body"><span>Lorem ipsum</span></div>
</li>
`)}
`)
);
html.resolve
returns update function, so it does not have to be wrapped with additional html
call.
from hybrids.
from hybrids.
It is not required, but it is recommended and the easiest way. Of course I mean using promises inside of the html template.
Feel free to comment or re-open, if you have any other problems this subject.
from hybrids.
Could you please demonstrate other ways to do async stuff with Hybrids? I've used with redux and it was really easy, but I'd like to know how to do it in a more vanilla way.
Html.promise is a really cool stuff, but I'd like to know if there is other way without having to encapsulate my html inside html.promise
from hybrids.
Try to think about async stuff as something that is a promise in the synchronous world. Then you can do anything async in the library, but return a promise and consume it somehow. They can be simple getter - function which returns promises.
Redux example shows how to connect third-party code to cache mechanism. It doesn't have to be async. Redux is not async. However, the redux store update might be called by the external change and we want to listen to that. In that sense, you should use the third argument in the connect()
callback to connect your external API - it can be anything - setTimeout, web socket, Geolocation API, whatever.
html.resolve
is a helper to consume promises and async values in templates. If I would compare to lit-html
it works pretty the same here and there. The only difference is, that lit-html
has until()
directive. If you have any ideas on how to make it simpler, I am here to listen to you :)
from hybrids.
is it possible to have an async / promise property factory that normalizes async data?
for example:
define("my-app", {
data: promisePropertyFactory(defaultValue, serviceApiCall("/my/api/endpoint"));
})
from hybrids.
I would suggest passing a promise as a value of the property as I wrote before. Then you can utilize a promise in the template by html.resolve
helper. However, if you want to have the data from a promise in the property, the only way is to call your async API in the connect
method:
MyApp = {
data: {
connect(host, key) {
host[key] = defaultValue;
serviceApiCall(...).then(data => { host[key] = data });
},
},
}
You can always create the factory from property structure, like this:
function promiseFactory(promise, defaultValue) {
return {
connect(host, key) {
host[key] = defaultValue;
promise.then(data => { host[key] = data });
},
}
const MyApp = {
data: promiseFactory(callMyApi("/api"), "test"),
};
Keep in mind that this solution has a significant downside. Connect method is called whenever the element is connected to the parent element - it means, that moving your element around will re-fetch data (and pass defaultValue). Even though it stays, fetch will be done only once, and cannot dynamically relay on other properties.
Because of that, the better way (and more declarative) is to pass your async function inside of the property getter:
const MyApp = {
data: ({ otherProperty }) => callMyApi(`/api/${otherProperty}`),
};
The data property will always return a promise - but only a new one when otherProperty
changes. It might look strange at first (we get used to working on data rather then promises). I understand your concerns, and I actively working on a built-in solution to store async data inside of the hybrids ecosystem. Please stay tuned for updates, and for now, use possible solutions.
from hybrids.
Related Issues (20)
- import as node module (import {...} from 'hybrids') doesn't work HOT 3
- Update to documentation HOT 2
- Custom methods on component ? HOT 2
- Tailwind integration HOT 2
- Update Store based on previous value HOT 10
- How to compile statically? HOT 5
- Typing Issue When Redefining HTMLElement Built-In Properties HOT 2
- 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
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.