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

Tighter React.JS integration, composable classes, modular animations. #20

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

johncant
Copy link

I've done some refactoring and got rudimentary composable classes working, without losing any functionality. I've also factored out animations into their own modules. This should make native class interop a lot easier. I ended up changing quite a lot of things. Happy to discuss and change a few things if necessary.

  • The state is now stored inside the React.JS state. Changing the state rerenders the component via React.JS.
  • Animations are now an optional extra. All the code outside of React.Anim and React.Anim.Class is completely oblivious to animations.
  • React.Class is now directly equivalent to a React.JS class with no animations. All transitions happen immediately. It made sense if there were going to be no animations. Signals delayed until first animation frame [question] #18
  • React.Anim.Class is like React.Class but with animations. The constructor arguments are pretty much unchanged. The animation state is stored as normal React.JS state. All transitions are now immediate.
  • Since ReactT no longer contains knowledge of the animation state, I removed getAnimationState in favour of an argument to the HS render function.
  • Compose classes via reactClass_. (No props yet. Do we even need them as an explicit argument?) first class classes #8
  • Examples updated but I could only get 3 to work in master (Simple, Circles, and Chain), so these are the only 3 I've tested so far. How to run the examples? #7
  • Interop should now be easier, since we can compose classes, and each ReactClass is now an actual JS React Class - we might have to change the code slightly for React 0.13.0. native class interop #9

}

function js_performance_now() {
return window.performance.now();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to self: think about polyfilling

@joelburget
Copy link
Owner

This is really cool. Will play around with this and get back with more detailed feedback later.

@johncant
Copy link
Author

Thanks for taking a look! * awaits feedback *.

@joelburget
Copy link
Owner

Hey John, I did some work on merging this after the recent switch to GHCJS. I've made some good progress but it's not working yet. Think you could take a look?

@johncant
Copy link
Author

Maybe later this week. Why have you switched to GHCJS? I tried GHCJS once and found that it produced megabytes of runtime and ran really slowly (of course I haven't benchmarked it properly). Will it still work on Haste?

@jeremyjh
Copy link
Contributor

@johncant I had this question too. I think ghcjs runtime is more like 100kb now once its been minified - but yes it is a lot heavier than Haste. What worries me is not the size but the complexity of the runtime implementation. Haste has 400 LOC in the runtime. I'm not sure ghcjs runtime could be maintained by anyone other than luite.

@joelburget would you accept a PR that kept it runnable on Haste or are you done with Haste?

@joelburget
Copy link
Owner

Good question. Sorry for making that switch out of nowhere. I decided to switch because as far as I can tell GHCJS seems to have more of a future than Haste. I think this for two reasons.

First, Haste is very fragile. A lot of packages couldn't build. For example, the current install directions include running haste-inst install --flags="-integer-gmp" hashable, then actually installing with haste-inst install (see issue #14). I could never get a lot of packages to build (affine, lens, etc). I also kept breaking my environment and having to reboot (likely my fault).

Second, and more importantly, GHCJS seems to have a more vibrant community. As far as I can tell it has more users and there seems to be a decent amount of activity. I recently sent a couple announcements to the Haste mailing list, to almost no response (thanks Jeremy :) ) (and there haven't been messages about other topics), which was a big red flag to me. I worry that it would be up to me to improve things (like making the build more robust). My main project is an application, so I really don't want to lose focus to such low level stuff (I found myself never getting to work on the things I really care about). Really what I'm looking for is a very stable platform to build on.

I'd love to hear your thoughts @johncant and @jeremyjh.

@jeremyjh I think it would be possible to run on either GHCJS or Haste by using different backends.

@johncant
Copy link
Author

I found both GHCJS and Haste a nightmare to set up (they both took me 2 whole days), so I used Vagrant, but for me that solves the installation difficulties in Haste. Haste's main failing as a language/compiler is that it doesn't support TemplateHaskell which breaks lots of packages. Are you sure you messaged the right mailing list? The last commit in haste-compiler was 5 days ago, and I'm pretty sure that compiling any Haskell into JavaScript is a pretty niche thing to want to do.

I'm all for using both and the biggest problem I can see is that using TemplateHaskell would break all the code for Haste.

Do you think GHCJS will end up being as small or as fast as Haste in the near future?

@joelburget
Copy link
Owner

+100 on being a pain to set up :( In fact I'm planning to upload the vagrant box I'm currently using - more or less the box I wish I could have just downloaded a few weeks ago - so anyone can get started easily with GHCJS.

I don't think template haskell is at all an issue for this package. It's not currently used and I don't have plans to use it (well, except for the todomvc example, but that could be changed).

Do you think GHCJS will end up being as small or as fast as Haste in the near future?

I really have no way of knowing :( Do you have speed benchmarks?

@johncant
Copy link
Author

johncant commented Apr 5, 2015

In the interests of getting this pull request merged and react-haskell working on Haste and GHCJS, Here's my Vagrant setup for Haste and this branch: https://gist.github.com/johncant/6a337759304b0e473659 . It should work without any modifications. Unfortunately, haste-compiler master breaks this PR at the moment.

I'm glad you don't need template haskell much. I don't have any benchmarks but it would be really easy to build them using react-haskell if it compiled on both GHCJS and Haste!

@johncant
Copy link
Author

johncant commented Apr 7, 2015

I'm going to need to spend more time on this understanding GHCJS's compiled output. Haste's compiled output took ages to get my head round, and GHCJS looks like it has even less documentation and is more complicated. Not that I expect documentation. How do you know what symbols like h$cN and h$ap1_e mean? Can you give me any pointers?

I have to say that I noticed the page lagging with GHCJS, but I can already tell that it's far superior from the development side.

@johncant
Copy link
Author

johncant commented Apr 9, 2015

Tried reductio ad absurdum:
https://gist.github.com/johncant/ce2fdf37713396dba069

There's an issue in GHCJS about this:
ghcjs/ghcjs#256

luite argues that this case (i.e exactly what we're trying to do in this PR) isn't necessarily a good idea, because a React JS render could trigger untold amounts of computation to take place. The solutions to this problem are to buffer the computations beforehand in another thread or evaluate certain things strictly beforehand. He's implemented his own virtual DOM with this in mind - https://github.com/ghcjs/ghcjs-vdom

When I call a Haskell callback from JS, I can't get a result back. h$runSync just crashes and normal JS execution just returns null. However, passing arguments to the callback works. Therefore (and luite mentions this) we can pass a callback that modifies its args or closure. This works however, but I don't like it, and it's clearly going to break when someone waits until the next JS tick to call the callback back:

https://gist.github.com/johncant/1a7b3533a32417adb201

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants