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

BUG: await tag errors on rerender #675

Open
jasonmacdonald opened this issue Apr 20, 2017 · 9 comments
Open

BUG: await tag errors on rerender #675

jasonmacdonald opened this issue Apr 20, 2017 · 9 comments
Labels
type:feature A feature request

Comments

@jasonmacdonald
Copy link
Contributor

jasonmacdonald commented Apr 20, 2017

Bug Report

Context

If you have an await tag in a template that only gets rendered by an action, like setting state after the initial render, the await tag will error. The "$__sync" property is set to true by the updateManager.$__batchUpdate().

You get the following error Uncaught Error: Not allowed.

Expected Behavior

It should run the await tag and wait for the promise to be fulfilled.

Actual Behavior

Throws an uncaught error.

Simple Example

This is a very simple example

class {
    onCreate(){
        this.state = {
            promise: Promise.resolve(),
            selected: false
        }
    }
}
<div>
    <if(state.selected)>
        <await(p from state.promise)>
            done
        </await>
    </if>
    <else>
        I show first
    </else>
    <a href="#" onClick('setState','selected', true) >click me</a>
</div>
Additional Info

Your Environment

  • Version used: 4.2.8
  • Environment name and version (e.g. Chrome 39, node.js 5.4): Chrome
  • Operating System and version (desktop or mobile): Windows 10

Stack Trace

AsyncVDOMBuilder.js:171 Uncaught Error: Not allowed
at r.beginAsync (AsyncVDOMBuilder.js:171)
at t.exports (await-tag.js:231)
at r (index.html:33)
at renderer.js:195
at Component.js:525
at Object.s [as $__batchUpdate] (update-manager.js:63)
at n.$__rerender (Component.js:520)
at n.update (Component.js:470)
at o (update-manager.js:44)
at i (update-manager.js:16)

@jasonmacdonald jasonmacdonald changed the title BUG: await tag errors if rendered by update-manager BUG: await tag errors on rerender Apr 20, 2017
@ianvonholt
Copy link
Contributor

This is happening in 4.3.1 as well with callback and promises in the await tag.

@emilklindt
Copy link

This bug is still occurring in version 4.4.21, August 7th.

In case it helps, here is a log printout of the error in-browser:

15:20:24.450 AsyncVDOMBuilder.js:182 Uncaught Error: Not allowed
    at AsyncVDOMBuilder.beginAsync (AsyncVDOMBuilder.js:182)
    at awaitTag (await-tag.js:230)
    at Object.renderBody (index.marko.js:57)
    at doInclude (include-tag.js:13)
    at includeTag (include-tag.js:30)
    at render (index.marko.js:64)
    at renderCompontent (renderComponent.js:3)
    at render (index.marko.js:32)
    at renderer (renderer.js:198)
    at Component.js:540
beginAsync @ AsyncVDOMBuilder.js:182
awaitTag @ await-tag.js:230
renderBody @ index.marko.js:57
doInclude @ include-tag.js:13
includeTag @ include-tag.js:30
render @ index.marko.js:64
renderCompontent @ renderComponent.js:3
render @ index.marko.js:32
renderer @ renderer.js:198
(anonymous) @ Component.js:540
batchUpdate @ update-manager.js:63
___rerender @ Component.js:517
initComponent @ init-components-browser.js:92
(anonymous) @ init-components-browser.js:191
initServerRendered @ init-components-browser.js:189
(anonymous) @ localhost/:62
(anonymous) @ localhost/:62```

@patrick-steele-idem
Copy link
Contributor

Here is my response on Gitter:

We've had some discussions on this internally and need to revisit. Right now, a re-render of a UI component must be synchronous. The reason for this limitation is that there can be unexpected behavior if there are multiple outstanding re-renders that may complete at various times. The recommended solution right now is to now is to not use the <await> tag inside a UI component that is to be re-rendered in the browser. As an alternative, if you need to asynchronously fetch data in the browser then introduce an intermediate "loading" state that triggers a re-render and when the data is available then do another re-render with the actual data from the backend. Does that work for you?

@cameronbraid
Copy link
Contributor

@patrick-steele-idem any idea when <await> may be supported int he browser ?

I have some components that use isomprphic fetch and want to use await on the server to render server side when the data is available, then on the browser it only re-renders when inputs change (which may trigger another fetch)

I can't seem to get a workaround working

I tried a component like this :

ServerAwait.marko

static const onserver = typeof window == 'undefined'
<if (onserver && input.promise)>
  <await(p from input.promise)>
    <include(input.renderBody)/>
  </await>
</if>
<else>
  <include(input.renderBody)/>
</else>

and it gets me pretty close.. it ends up with a flash of no content when the client re-renders until the client has fetched the data again. One workaround could be to add a new argument to the await tag that takes a function returning a promise. If the await tag could retain the rendered dom until this new promise is resolved, it would then re-render nicely.

@StarpTech
Copy link
Contributor

What's the status? There are problems with communication. In #942 it was a high priority, now it just ignored. This issue contradicts the whole argument of "isomorphic code" for markojs.

@DylanPiercey
Copy link
Contributor

DylanPiercey commented Mar 13, 2019

@StarpTech the tricky piece here is making it so that if you have a promise that is only rendered server side that it is serialized to the browser so that a hydrate can take place as normal.

Our current thinking (although we have not had time to look at this holistically) would be to add promise serialization to warp10 which is what Marko uses internally to send the initial input to the browser for the first render.

We have quite a few things on the go and this keeps getting pushed to the back burner but it is something that is a must have before or shortly after the release of Marko 5.


I will add that @patrick-steele-idem's solution is still a viable work around here.

@StarpTech
Copy link
Contributor

@DylanPiercey thank you for the fast response. Currently, I run into this because I have no clue why my component was marked as "client" side code. #1285 (comment)

@jetrii
Copy link

jetrii commented Jun 4, 2021

Hi all. Is there an update on this issue now that Marko 5 is out?

@DylanPiercey
Copy link
Contributor

@jetrii no update as of yet. It is one of the things we want to get right in Marko 6. For now the recommendation is still the same, if you need the await client side it's best to use state to store loading / result / error data and display accordingly.

There is also my fairly hacky work around (https://gist.github.com/DylanPiercey/9d65759ffa4ff7752a2bc8aa74f5da40). For the most part it works, but doesn't support client-reorder.

@DylanPiercey DylanPiercey added type:feature A feature request and removed type:bug A bug report labels Dec 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:feature A feature request
Projects
None yet
Development

No branches or pull requests

9 participants