peerlibrary / meteor-blaze-components

Reusable components for Blaze
http://components.meteorapp.com/
BSD 3-Clause "New" or "Revised" License
354 stars 26 forks source link

Ideas for new features of Blaze Components #139

Open mitar opened 8 years ago

mitar commented 8 years ago

I am not yet completely sure how I would implement this, but I am thinking of doing some backwards incompatible changes to Blaze Components. In short, it is getting rid of a data context, instead of replacing it with scope.

What my plan is that I bump this package to 1.0 and release it. And then the above changes will be 2.0 of this package.

So the API of a component are arguments you can pass, and public methods you can call on the component. Events handlers are internal to the component.

cc @stubailo, because I think he will like some ideas here

stubailo commented 8 years ago

getting rid of a data context, instead of replacing it with scope

Yes please!!

arguments can be marked as constructor-level argument, or render-level argument

Not sure what this means? Also, there are so many ways to specify types of arguments... React PropTypes, Meteor Match, etc. which one do we use?

each argument is exposed as a method on the component

Perhaps this.args.x? Or we just expect people to avoid collisions? Maybe we can just warn on collisions.

Events handlers are internal to the component.

So should people use the React-style callback passing to set event handlers on children?

mitar commented 8 years ago

arguments can be marked as constructor-level argument, or render-level argument Not sure what this means?

In Blaze Components you have two types of data which can come to a component. One is what is passed to the component's constructor, another is which is currently a data context. The difference is that if the first arguments change, we recreate/reinitialize the component, if a second argument changes, only the state of the component changes, and things re-render reactivelly.

Currently, you could pass or another, but not both. And now I am proposing that this is simply metadata of the argument, how it should be provided to the component (and which time).

Also, there are so many ways to specify types of arguments... React PropTypes, Meteor Match, etc. which one do we use?

None, as specified above, so that we do not force evaluation of a reactive function passed.

Or we just expect people to avoid collisions? Maybe we can just warn on collisions.

To me arguments is something you would add to your component inside a constructor. You should make sure you do not clobber any prototype method you have there anyway. And yes, we could check if a component has a prototype method defined the same as you defined that potentially arguments could be.

So should people use the React-style callback passing to set event handlers on children?

So, arguments can be functions. And so yea, you could do onClick={{argumentPassedFromParent}} in a child template, probably. Or your child template could do onClick={{parent.childOnClick}} if parent was passed as an argument to child component, and has childOnClick as a public method. So in the latter case there is a constraint on what types of parent values are allowed, one with childOnClick public methods.

dorseth commented 8 years ago

It would be great to have something like reacts componentDidUpdate, sometimes you have to use jQuery libs and stuff like this saves time (in the situations when you receive new data, but the template already rendered, but you need jQuery to do something with new data);

It's quite hacky and not the intended way of properly doing things, but well, every time I hit this kind of situation I need to reinvent the wheel :) .

caioreis commented 8 years ago

@mitar everything looks awesome here, and I'm very excited to see public methods as one of the priorities. I'm not going to comment everything because I agree with all the changes, but I can suggest implementations (as a new but already heavy user view).

One thing that we already created is a sharedState variable to be our central reactive source between components. I identify all components at startup and create a reactive data source for each one that can be used and accessed by all components. Is that something to consider? If yes, I have some ideas.

stubailo commented 8 years ago

I identify all components at startup and create a reactive data source for each one that can be used and accessed by all components. Is that something to consider? If yes, I have some ideas.

Isn't this the same as Session?

caioreis commented 8 years ago

@stubailo Session can be used here, but I'm thinking in something more scoped to the component it self. Using Session would require me and my team to be careful about variable names and everything. What we are doing is something like this:

commonState.componentName.VariableName()

This way we know that this is a variable that has componentName as parent. It's a simple (mostly because of ReactiveVar 😄 ) implementation but that makes sense for us.

We are thinking about changing the method to something like this this.shareState('foo', bar);. And in another component I can use this.getState('component', 'foo');.

At least for us this makes a lot of sense. I can already think about some implications of this implementations. For example, what if I have multiple components rendered on the page? That means that all of them will share the same state? Maybe yes, maybe no.

Does it makes sense for you now, @stubailo ? If no, I would love to hear maybe a simpler implementation that we can use.

stubailo commented 8 years ago

I guess that seems just as global, since it's just like saying Session.get('componentName/variableName') but if it works for you that's great!

mitar commented 8 years ago

It would be great to have something like reacts componentDidUpdate, sometimes you have to use jQuery libs and stuff like this saves time (in the situations when you receive new data, but the template already rendered, but you need jQuery to do something with new data);

When should this run? On every change? Of any attribute of any dom element?

One thing that we already created is a sharedState variable to be our central reactive source between components.

Why don't you just use Minimongo/local collections on the client? It has nice things like easy limiting of reactivity, complex queries against data, and so on? You could have one document per component. You could in onCreated create such document, if you for example to have independent state per each component.

But anyway, this is for me orthogonal question to view layer. I do not think this should be part of the view layer, but it should just allow its use. Personally, I do not see the benefit of what you are proposing. But everyone has its own preferences here.

dorseth commented 8 years ago

Yeah, looks like I did it the wrong thing all the way, though I used the client-side collections. Thank you :)