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

Scaffold components #2

Closed
yoshuawuyts opened this issue Nov 10, 2017 · 21 comments · Fixed by #6
Closed

Scaffold components #2

yoshuawuyts opened this issue Nov 10, 2017 · 21 comments · Fixed by #6

Comments

@yoshuawuyts
Copy link
Member

Once we settle on choojs/choo#593, choo-scaffold should be able to create components too. This is probably the main reason why this module exists in the first place, as creating components requires a fair bit of boilerplate.

@YerkoPalma
Copy link
Member

@choojs/trainspotters what would be a good boilerplate for components here?? I want to implement this.

Is something like this ok?

var Component = require('choo/component')
var html = require('choo/html')

class component extends Component {
  constructor () {
    super()
  }

  createElement () {
    return html`
      <div>
      </div>
    `
  }

  update () {
    return false
  }
}

module.exports = component

@kareniel
Copy link
Member

That's what I would go for personally.

@goto-bus-stop
Copy link
Member

Same, I like that!

@nicknikolov
Copy link

I feel like update returning false by default might cause some mild headaches to people choo-ing for the first time? But might be fine.

@YerkoPalma
Copy link
Member

There's no special reason to set it to false, so I could change it to true by default.

@ungoldman
Copy link
Member

LGTM! I think defaulting to createElement accepting state, emit as parameters (and update too) is a small but important convention worth adopting.

@YerkoPalma
Copy link
Member

Agree. So this might be a better default?

var Component = require('choo/component')
var html = require('choo/html')

class component extends Component {
  constructor () {
    super()
  }

  createElement (state, emit) {
    return html`
      <div>
      </div>
    `
  }

  update (state, emit) {
    return true
  }
}

module.exports = component

@tornqvist
Copy link
Member

tornqvist commented Jun 21, 2018

Assuming the component is to be rendered with the new component cache I think it'd make sense to reflect the signature imposed by the cache. It'd also help educate users on how to use the new component cache and encourage its use.

The constructor will have the component cache id, state and emit prefixed to the arguments. Also, with the introduction of choo/component the components property was added to the state. The intention of this was to have a shared space for all stateful things, including local component state, see reasoning for it here. @yoshuawuyts introduced the pattern of assigning a branch of the shared component state to this.local which I think is quite nice.

constructor (id, state, emit) {
  super(id)
  this.local = state.components[id] = {}
}

Idk if it'd make sense to assign state and emit to this in the constructor or if that's better left up to the user but either way there'd be no need to have them as default args to createElement.

@goto-bus-stop
Copy link
Member

yeah using the API that state.cache() uses would be best 👍

@YerkoPalma
Copy link
Member

I'm ok with passing those arguments to the constructor, it will help a lot to folks like me :)

I think is up to the developer how those are used, that's why I wouldn't assign them to this in the constructor. Now, I would keep state in createElement, because if the state of the choo app change outside the component, we might want to keep it synced inside.

@YerkoPalma
Copy link
Member

So, for now component boilerplate would be like this

$ choo-scaffold component custom-button
var Component = require('choo/component')
var html = require('choo/html')

class CustomButton extends Component {
  constructor (id, state, emit) {
    super(id)
    this.local = state.components[id] = {}
  }

  createElement (state, emit) {
    return html`
      <div>
      </div>
    `
  }

  update (state, emit) {
    return true
  }
}

module.exports = CustomButton

if everyone is ok I will update the PR #6

@YerkoPalma
Copy link
Member

YerkoPalma commented Jun 21, 2018

PR updated 👍

@ungoldman
Copy link
Member

ungoldman commented Jun 21, 2018

This may be a little off-topic but I can't see why state and emit are getting passed to the Component constructor for the cache from looking at the cache source. AFAIK Nanocomponent isn't designed to do anything with state or emit until the first render, right? cc @bcomnes

EDIT: sorry just saw the this.local = state.components[id] = {} line above.

Still confused on intended usage, how much component has to know about cache, etc., but this is off-topic.

@tornqvist
Copy link
Member

@ungoldman The idea was to pass them to the constructor so that you wouldn't have to manually pass state and emit through the render method. I've been using it a lot as a way to share the component cache without having to pass it through the render call. I've also found that having emit attached to the component is very useful for wrapper components which only delegate callbacks to it's child components. This is what my component constructor boilerplate usually look like nowadays:

constructor (id, state, emit) {
  super(id)
  this.emit = emit
  this.cache = state.cache
  this.local = state.components[id] = {}
}

@YerkoPalma
Copy link
Member

@tornqvist you keep a cache reference in component to render other components? like component container pattern described in nanocomponent docs?

@tornqvist
Copy link
Member

That's right @YerkoPalma. Since the introduction of component cache in Choo core I only manually handle component instances when absolutely necessary and use state.cache otherwise. The fact that the constructor get the state (and hence, the cache) as an argument makes it very easy to have all components in the app at any depth share the same cache without much boilerplate at all.

@YerkoPalma
Copy link
Member

Merged! but I can't publish 😶

@goto-bus-stop
Copy link
Member

@YerkoPalma yosh added it to the org just now, you should be able to publish :)

@ungoldman
Copy link
Member

@YerkoPalma you should be able to publish to npm, looks like you're on the access list: https://www.npmjs.com/package/choo-scaffold/access

@ungoldman
Copy link
Member

haha woops looks like @goto-bus-stop and yosh already took care of it at the exact time I looked 👀

@YerkoPalma
Copy link
Member

haha nice! just got published as 1.2.0 🎉

thank you all :)

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 a pull request may close this issue.

7 participants