-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4016 from WordPress/add/with-state
Components: Add withState higher-order component
- Loading branch information
Showing
5 changed files
with
135 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
withState | ||
========= | ||
|
||
`withState` is a React [higher-order component](https://facebook.github.io/react/docs/higher-order-components.html) which enables a function component to have internal state. | ||
|
||
Wrapping a component with `withState` provides state as props to the wrapped component, along with a `setState` updater function. | ||
|
||
## Usage | ||
|
||
```jsx | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { withState } from '@wordpress/components'; | ||
|
||
function MyCounter( { count, setState } ) { | ||
return ( | ||
<> | ||
Count: { count } | ||
<button onClick={ () => setState( ( state ) => ( { count: state.count + 1 } ) ) }> | ||
Increment | ||
</button> | ||
</> | ||
); | ||
} | ||
|
||
export default withState( { | ||
count: 0, | ||
} )( MyCounter ); | ||
``` | ||
|
||
`withState` optionally accepts an object argument to define the initial state. It returns a function which can then be used in composing your component. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { Component, getWrapperDisplayName } from '@wordpress/element'; | ||
|
||
/** | ||
* A Higher Order Component used to provide and manage internal component state | ||
* via props. | ||
* | ||
* @param {?Object} initialState Optional initial state of the component | ||
* @return {Component} Wrapped component | ||
*/ | ||
function withState( initialState = {} ) { | ||
return ( OriginalComponent ) => { | ||
class WrappedComponent extends Component { | ||
constructor() { | ||
super( ...arguments ); | ||
|
||
this.setState = this.setState.bind( this ); | ||
|
||
this.state = initialState; | ||
} | ||
|
||
render() { | ||
return ( | ||
<OriginalComponent | ||
{ ...this.props } | ||
{ ...this.state } | ||
setState={ this.setState } | ||
/> | ||
); | ||
} | ||
} | ||
|
||
WrappedComponent.displayName = getWrapperDisplayName( WrappedComponent, 'state' ); | ||
|
||
return WrappedComponent; | ||
}; | ||
} | ||
|
||
export default withState; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { mount } from 'enzyme'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import withState from '../'; | ||
|
||
describe( 'withState', () => { | ||
it( 'should pass initial state and allow updates', () => { | ||
const EnhancedComponent = withState( { count: 0 } )( ( { count, setState } ) => ( | ||
<button onClick={ () => setState( ( state ) => ( { count: state.count + 1 } ) ) }> | ||
{ count } | ||
</button> | ||
) ); | ||
|
||
const wrapper = mount( <EnhancedComponent /> ); | ||
|
||
expect( wrapper.html() ).toBe( '<button>0</button>' ); | ||
wrapper.find( 'button' ).simulate( 'click' ); | ||
expect( wrapper.html() ).toBe( '<button>1</button>' ); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters