-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Components: Add withState higher-order component #4016
Conversation
} | ||
edit: withState( { | ||
preview: false, | ||
} )( ( { attributes, setAttributes, setState, focus, preview } ) => [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we start using React.Fragment
to avoid using keys? Do we want to update Babel first? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we start using
React.Fragment
to avoid using keys? Do we want to update Babel first? :)
Yeah, I'd probably want to avoid the direct reference to React.Fragment
, but if we had <>
syntax available, I'd be open to using it. Maybe in a subsequent pull request where we upgrade Babel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can spin up PR with Babel upgrade on Monday :)
return ( | ||
<> | ||
Count: { count } | ||
<button onClick={ () => setState( { count: count + 1 } ) }> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noting that React docs discourage using setState( { count: count + 1 } )
this way when it depends on props:
React may batch multiple
setState()
calls into a single update for performance.Because
this.props
andthis.state
may be updated asynchronously, you should not rely on their values for calculating the next state.
They suggest using the following:
setState( count => ( { count: count + 1 } )
See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous. I think we should follow those guidelines in here, and in the unit test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should follow those guidelines in here, and in the unit test.
Updated in rebased 6fba36d.
} | ||
} | ||
|
||
WrappedComponent.displayName = getWrapperDisplayName( WrappedComponent, 'withState' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In other places, I omitted with
prefix for the display name. We should either update all existing getWrapperDisplayName
calls or put state
here instead. Both work for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should either update all existing
getWrapperDisplayName
calls or putstate
here instead.
Updated in rebased 6fba36d.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this HOC a lot. This is exactly what we need to make it possible to use state with functional components or when using ES5 only. Great work 💯
I left some minor comments. They aren't blockers, but taking into account that we are updating docs we might want to be super strict and align with React docs :)
c5fe8d9
to
925acf9
Compare
This is great, thanks for doing it! |
Do we really want to add an maintain this kind of API? Do we really want to optimize for the ES5 use-case?
|
I would advocate for full support for ES5 style as long as it is the only way to avoid build step.
We might advertise
|
Personally I think we should seek to be as inclusive as possible to those who choose not to include a build step. Also, arguably one of the points of this change was that it's an obvious pattern for introducing state even for those who choose to use newer language syntax.
Recompose includes a fair bit more functionality that may be overwhelming for those who are simply trying to maintain some local component state. It's hard to draw a line between what we do and don't want to support and maintain ourselves. I think something like this covers a pretty good baseline option without needing to reach for more powerful solutions.
As mentioned in #3435, I don't think we should encourage
We could introduce a HoC for lifecycle, but instead I'd be curious to identify the use-cases that would call for lifecycle in block implementations and see if we can address those with more targeted utilities. |
It might make sense to have |
Thanks for working on this. I do like this API and would like to see how we could use it for our own components as well, as it seems inherently more flexible in not tying to a library but tying to WP patterns instead. |
I asked on Twitter the following:
|
Supersedes #3435
This pull request seeks to add a new
withState
higher-order component to enable ES5 block implementers to introduce state to their components without reaching for theComponent
class.View documentation
Included is an example porting the HTML block component to a stateless function component using
withState
.Testing instructions:
Verify that there are no regressions in the behavior of toggling between Preview and HTML in the HTML block.