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

Question about lifecycle, internal component state #50

Closed
jonjaques opened this issue Aug 28, 2017 · 6 comments
Closed

Question about lifecycle, internal component state #50

jonjaques opened this issue Aug 28, 2017 · 6 comments

Comments

@jonjaques
Copy link

Hello,

I'm wondering about how one would trigger a render from from inside a component mounted inside a choo app.

I'm referencing your leaflet component and the lifecycle diagram, and want to take a swing at a google maps one, but I'm having trouble figuring out how to emulate React's setState. Choo is cool because you have absolute control about when to rerender, but I can't wrap my head around how that gels with the ability of a component to trigger it's own render based on setState.

It seems that if I want render to be called on my component, I would have to pass in the emit fn? Is that the case, or is there a way I can force a render without any upstream dependencies?

Thanks for any help you could provide!

@bcomnes
Copy link
Contributor

bcomnes commented Aug 28, 2017

This is a common question. We should add an example to the README.

If you are handling events internally and need to trigger re-renders, you can just call this.render(args), so the only thing to decide on is how you want to handle arguments. On solution is caching arguments e.g.

var Nanocomponent = require('nanocomponent')
var html = require('bel')
var SomeEventEmitterThing = require('foo')

class Component extends Nanocomponent {
  constructor () {
    super()
    this.arguments = []
    this.bus = new SomeEventEmitterThing()

    this.handleInternalUpdates = this.handleInternalUpdates.bind(this)
  }

  handleInternalUpdates (someNewArg) {
     // re-render with old arguments
     this.render.apply(this.arguments)
  }

  createElement (foo, bar, baz) {
    this.arguments = arguments
    return html`
      <div>${foo} ${bar} ${baz}</div>
    `
  }

  update (newColor) {
    return false
  }

  load {
     this.bus.on('event', this.handleInternalUpdates)
  }

  unload {
   // usually there is no point to keep running render on unmounted components
    this.bus.removeListener('event',  this.handleInternalUpdates)
  }

}

@jondashkyle
Copy link
Collaborator

Yeah—an example in the readme would be helpful, but also think it could be worth exploring ways of making it more default, rather than needing to manually store the previous props, etc…

@jonjaques
Copy link
Author

Great, thanks! I did see the mention about caching internal args, but coming from React it scared me. That being said, I don't know enough about React internals and perhaps they do the same thing for purposes of comparing props. Will see about submitting a PR 😄

@bcomnes
Copy link
Contributor

bcomnes commented Aug 28, 2017

Agreed! One idea is that we auto-cache arguments and let you do something built in along the lines of this.bus.emit('render') and then the render function will get last args and whatever internal state you have changed. React does a lot of this stuff automatically, and one area this was exploring was not making these assumptions for people to cut down on API size and allow more freedom/creativity, but this is common enough to shortcut for people maybe.

@jondashkyle
Copy link
Collaborator

Definitely. I think having the render method and some form of internal state tracking while continuing to expose the internals, so if you want to manage it yourself nothing changes, could be a solid solution.

@bcomnes
Copy link
Contributor

bcomnes commented Aug 28, 2017

I think this idea might fit with #44

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

No branches or pull requests

3 participants