Code Monkey home page Code Monkey logo

Comments (15)

DavideCarvalho avatar DavideCarvalho commented on May 14, 2024

I tried to use invalidate method after the request, but still no success

from hybrids.

DavideCarvalho avatar DavideCarvalho commented on May 14, 2024

I removed the http request and put a mocked value, and it worked. Looks like promises doesn't work as it should

from hybrids.

smalluban avatar smalluban commented on May 14, 2024

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.

DavideCarvalho avatar DavideCarvalho commented on May 14, 2024

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.

DavideCarvalho avatar DavideCarvalho commented on May 14, 2024

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.

smalluban avatar smalluban commented on May 14, 2024

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.

DavideCarvalho avatar DavideCarvalho commented on May 14, 2024

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.

DavideCarvalho avatar DavideCarvalho commented on May 14, 2024

Even after changing getOngs implementation to:

export const getOngs = () => {
  return fetch(`${url}/ongs`)
    .then((res) => res.json());
};

The error stays

from hybrids.

smalluban avatar smalluban commented on May 14, 2024

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.

DavideCarvalho avatar DavideCarvalho commented on May 14, 2024

from hybrids.

smalluban avatar smalluban commented on May 14, 2024

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.

DavideCarvalho avatar DavideCarvalho commented on May 14, 2024

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.

smalluban avatar smalluban commented on May 14, 2024

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.

dredzone avatar dredzone commented on May 14, 2024

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.

smalluban avatar smalluban commented on May 14, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.