You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Sep 21, 2022. It is now read-only.
Repository navigation
This repository was archived by the owner on Sep 21, 2022. It is now read-only.
The trick is that render only returns a data structure of React elements. Something somewhere needs to know to take the return value from onClick and reconcile it with the previous exact structure that was present for this particular instance.
I'm working on a solution to this problem right now, and I came up with an updater binder as the third argument to render.
render(state,props,updater){return(<div><span>Clicked {state.count} times!</span><ahref="javascript:void(0)"onClick={updater((e,{props, state, updater})=>{count: state.count+1})}>
Click to increment!
</a></div>);}
@jordwalke Ah, got it. I also like your way with updater. My goal was to avoid using this and compose components from the export functions (but it's already in the section 👍 ).
So, I know it's too early to talk about it, but do you have any optimistic prognoses about implementing this?
IMO it's better to make context optional. Because of it's rare use. You don't need context if you don't have contextTypes for your component. BTW as I understand updater is also optional. So it might look like
I mean that it should be handful to omit some arguments (i.e. state, context, updater) if you don't need them in render function. Also I think order should be props first, then state, updater and context.
@FezVrasta It's kind of like doing .bind(this). With the returning-state pattern, there's no "this", and no reference to an actual component instance (which is actually one of the appeals). The updater(fn) event handler binder ensures that the state in the right location in the UI tree is updated with the return value of fn.
@FezVrasta With the this example you provided, there's some things that the updater pattern (imho) handles better. In your example, state can be read off of this, which implies that state must always be mutated to contain the new state. onClick={() => this.setState({ foo: this.state.foo + 1 })}
Mutation makes many things more difficult including (eventually) concurrency/parallelism. If you change your example slightly to use the alternative React setState API that accepts a callback, it's improved because it doesn't encourage relying on stalestate fields that must be mutated in order to be kept up to date:
This alternative React setState API has the benefit that the system can provide you the "freshest" props in the callback, which has many benefits. Then it becomes clear that this is actually very similar to the updater API. It has the same benefits such as not requiring mutation of this or this.state, and discourages trapping stale values in the event handling closure. updater just allows you to create your callback in this form (e, {props, state, updater}) => nextState which also would let you "chain" updaters by using the updater again even if the event handler was defined far away from the render function.
Note: in my original updater API I forgot to include the arguments to the callback (I just added them now).
Activity
jordwalke commentedon Jun 15, 2015
👍
The trick is that
renderonly returns a data structure of React elements. Something somewhere needs to know to take the return value fromonClickand reconcile it with the previous exact structure that was present for this particular instance.I'm working on a solution to this problem right now, and I came up with an
updaterbinder as the third argument torender.BTW: What syntax is that for default arguments?
Kureev commentedon Jun 15, 2015
@jordwalke Ah, got it. I also like your way with updater. My goal was to avoid using
thisand compose components from the export functions (but it's already in the section 👍 ).So, I know it's too early to talk about it, but do you have any optimistic prognoses about implementing this?
About the syntax - it's in the ECMA-262 proposal
chicoxyzzy commentedon Jun 15, 2015
what about
context?Kureev commentedon Jun 15, 2015
@chicoxyzzy I'd implement a context as one of the arguments:
chicoxyzzy commentedon Jun 15, 2015
IMO it's better to make
contextoptional. Because of it's rare use. You don't needcontextif you don't havecontextTypesfor your component. BTW as I understandupdateris also optional. So it might look likeKureev commentedon Jun 15, 2015
@chicoxyzzy What means "optional"? If you want, you can omit all attributes, use it like this:
If you're talking about order of arguments, then I guess
state,props,updater,contextchicoxyzzy commentedon Jun 15, 2015
I mean that it should be handful to omit some arguments (i.e.
state,context,updater) if you don't need them inrenderfunction. Also I think order should bepropsfirst, thenstate,updaterandcontext.kibin commentedon Jul 5, 2015
I think that render should take an object in which you can pass all the parameters. That way you can easily omit all that you don’t need:
FezVrasta commentedon Dec 21, 2016
I don't quite get what would be the purpose of the
updaterjordwalke commentedon Dec 21, 2016
@FezVrasta It's kind of like doing
.bind(this). With the returning-state pattern, there's no "this", and no reference to an actual component instance (which is actually one of the appeals). Theupdater(fn)event handler binder ensures that the state in the right location in the UI tree is updated with the return value offn.FezVrasta commentedon Dec 25, 2016
How preact achieves it then?
Once you have this code, everything should just work:
thisis still used forsetState, but who cares?Still better than:
jordwalke commentedon Dec 29, 2016
@FezVrasta With the
thisexample you provided, there's some things that theupdaterpattern (imho) handles better. In your example,statecan be read off ofthis, which implies thatstatemust always be mutated to contain the newstate.onClick={() => this.setState({ foo: this.state.foo + 1 })}Mutation makes many things more difficult including (eventually) concurrency/parallelism. If you change your example slightly to use the alternative React
setStateAPI that accepts a callback, it's improved because it doesn't encourage relying on stalestatefields that must be mutated in order to be kept up to date:This alternative React
setStateAPI has the benefit that the system can provide you the "freshest" props in the callback, which has many benefits. Then it becomes clear that this is actually very similar to theupdaterAPI. It has the same benefits such as not requiring mutation ofthisorthis.state, and discourages trapping stale values in the event handling closure.updaterjust allows you to create your callback in this form(e, {props, state, updater}) => nextStatewhich also would let you "chain" updaters by using theupdateragain even if the event handler was defined far away from therenderfunction.