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

Creating and rendering into a canvas #39

Open
justinlovinger opened this issue Jan 29, 2020 · 5 comments
Open

Creating and rendering into a canvas #39

justinlovinger opened this issue Jan 29, 2020 · 5 comments
Assignees

Comments

@justinlovinger
Copy link

I'm trying to create a canvas element containing an animation, but I'm not sure how to compose the canvas itself with the render Effect.

With React, you can use a componentDidMount callback to render on a canvas, when the canvas is created in the dom. However, I don't see anything like onComponentDidMount.

Currently, my solution looks like

canvasId ← liftEffect random
myCanvas ← canvas [ _id $ show canvasId, onClick ] []
_ ← liftEffect $ runCanvas canvasId
canvas [ _id $ show canvasId] []

This solution is not ideal for a few reasons. The onClick is just a placeholder to get the runCanvas effect to run, and ending with a second canvas feels like a hack.

I have also considered starting an asyncronous effect with a wait loop, before calling the first canvas, but then I have an unnecessary wait loop and might leave orphan scripts.

I'm not sure how to bundle a canvas element with it's corresponding render effect, without resorting to a workaround.

@ajnsit
Copy link
Member

ajnsit commented Jan 29, 2020

Unless I am misunderstanding your question, this sort of parallel UI composition is already well supported by Concur. Have you tried using <|> to compose the runCanvas in parallel with the canvas UI element, and not letting the runCanvas end by following it with empty -

do
  canvasId ← liftEffect random
  canvas [ _id $ show canvasId ] []
    <|> (liftEffect (runCanvas canvasId) *> empty)

@justinlovinger
Copy link
Author

Composing in parallel results in runCanvas running before the canvas element exists, requiring an asyncronous wait loop. It is another workaround, but it still isn't as clean as something like an explicit onMount callback.

@ajnsit
Copy link
Member

ajnsit commented Jan 29, 2020

Ah I see.

Synchronous actions are run "in-place" before populating the view, but asynchronous actions are run after the view is populated and stable, equivalent to doing it in componentDidMount. So something like this might do the trick -

do
  canvasId ← liftEffect random
  canvas [ _id $ show canvasId ] []
    <|> liftAff (liftEffect (runCanvas canvasId) *> empty)

Note that here we have pushed the empty inside the Aff. This makes sure that the Aff is not resolved synchronously.

@justinlovinger
Copy link
Author

Hmm, using liftAff like that results in a runtime error:

Aff failed - parcelRequire<["output/Effect.Exception/foreign.js"]</exports.error@http://localhost:1234/e31bb0bc.js:19985:10
parcelRequire<["output/Effect.Aff/index.js"]<@http://localhost:1234/e31bb0bc.js:40984:73
newRequire@http://localhost:1234/e31bb0bc.js:47:24
localRequire@http://localhost:1234/e31bb0bc.js:53:14
parcelRequire<["output/Concur.Core.Types/index.js"]<@http://localhost:1234/e31bb0bc.js:42723:25
newRequire@http://localhost:1234/e31bb0bc.js:47:24
localRequire@http://localhost:1234/e31bb0bc.js:53:14
parcelRequire<["output/Component.Indicator/index.js"]<@http://localhost:1234/e31bb0bc.js:46325:32
newRequire@http://localhost:1234/e31bb0bc.js:47:24
localRequire@http://localhost:1234/e31bb0bc.js:53:14
parcelRequire<["output/Component.App/index.js"]<@http://localhost:1234/e31bb0bc.js:61772:34
newRequire@http://localhost:1234/e31bb0bc.js:47:24
localRequire@http://localhost:1234/e31bb0bc.js:53:14
parcelRequire<["output/Main/index.js"]<@http://localhost:1234/e31bb0bc.js:95989:28
newRequire@http://localhost:1234/e31bb0bc.js:47:24
localRequire@http://localhost:1234/e31bb0bc.js:53:14
parcelRequire<["index.js"]<@http://localhost:1234/e31bb0bc.js:96008:36
newRequire@http://localhost:1234/e31bb0bc.js:47:24
parcelRequire<@http://localhost:1234/e31bb0bc.js:81:17
@http://localhost:1234/e31bb0bc.js:120:3

Although, even if the runtime error is fixed, it still feels more like a workaround than intended behaviour. It's not clear from the code that liftAff means "wait for the component to mount, then do this", and I think it is a common enough usecase to get proper support.

@ajnsit
Copy link
Member

ajnsit commented Jan 30, 2020

Hmm, that seems like a bug. I'm looking at it.

@ajnsit ajnsit self-assigned this Jan 30, 2020
@ajnsit ajnsit added the bug label Jan 30, 2020
ajnsit added a commit that referenced this issue Apr 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants