react-wormhole-hoc
v0.0.0react-wormhole-hoc
A better alternative to react context.
Motivations
Context is a very powerful feature in React, but it may get you into trouble sometimes.
See these issues for detail:
- https://medium.com/@mweststrate/how-to-safely-use-react-context-b7e343eff076
- https://github.com/facebook/react/issues/2517
Features
- Works well with
shouldComponentUpdate
andReact.PureComponent
- No namespace conflict
- Works well outside React Component
- Can communicate without parent-child relationship
Quick Start
import React, { Component, PropTypes } from 'react';
import Wormhole from 'react-wormhole-hoc';
const storeWormhole = new Wormhole({ content: '...' })
const fetchData = () => new Promise((resolve) =>
setTimeout(() => resolve({ content: 'awesome!!1' }), 1000)
);
@storeWormhole.hoc('myStore')
class DeepChild extends Component {
static propTypes = {
myStore: PropTypes.object,
};
render() {
return (
<div>
content: {this.props.myStore.content}
</div>
);
}
}
class NoUpdate extends Component {
shouldComponentUpdate() {
// no update
return false;
}
render() {
return (
<DeepChild />
);
}
}
class App extends Component {
componentDidMount() {
fetchData('/fake/api').then((store) => {
storeWormhole.set(store);
});
}
render() {
return (
<NoUpdate />
);
}
}
For more usage, please check the ./example
directory, or clone this repo and run npm run example
to start live demo.
API
constructor(initialValue)
Create wormhole instance.
Arguments
- initialValue (Any): Initial value.
Return
(Wormhole): wormhole
instance.
get()
Get current value. Will emit an get
event.
Return
(Any): Value.
set(newValue)
Set new value. Will emit an set
event. If the newValue
is different with the old value, it will also emit an change
event.
Arguments
- newValue (Any)
on(event, handler)
Listen for a custom event on the current instance.
Arguments
- event (String): Event type.
- handler (Function): Event handler.
Return
(Function): off.
once(event, handler)
Listen for a custom event, but only once.
Arguments
- event (String): Event type.
- handler (Function): Event handler.
Return
(Function): off.
off([event, handler])
Remove event listener(s).
Arguments
- event (String): Event type.
- handler (Function): Event handler.
hoc(propName)
Create React HOC.
Arguments
- propName (String): Inject this value as
prop
.
Return
(Function): A HOC creator function.
Example
Basic usage:
import React, { Component, PropTypes } from 'react';
import Wormhole from 'react-wormhole-hoc';
const myWormhole = new Wormhole('awesome!!1');
class App extends Component {
static propTypes = {
myValue: PropTypes.string,
};
render() {
return (
<h1>{this.props.myValue}</h1>
);
}
}
const hoc = myWormhole.hoc('myValue');
export default hoc(App);
With transform-decorators-legacy babel plugin:
@myWormhole.hoc('myValue')
export default class App extends Component {
// the same with above...
}
static connect(mapProps[, options])
Connect some wormholes to a HOC.
Arguments
- mapProps (Object|Function): Define a key-value object to
props
. Avalue
should be awormhole
instance or a function. If avalue
is a type ofString
,Number
,Boolean
,Array
or a plain Object, it would be converted towormhole
instance. - options (Object): See below for detail.
Available options:
- isPure (Boolean): Use
pureComponent
or not. Default value:true
. - withRef (Boolean): If true, stores a ref to the wrapped component instance and makes it available via
getWrappedInstance()
method. Default value:false
. - hoistMethods ([String]): Copies wrapped component instance methods to HOC instance. Make sure set
withRef: true
first. Default value:[]
.
Example
Basic usage:
@Wormhole.connect({
hello: 'hello',
/* or: */
// hello: new Wormhole('hello'),
world: 'world',
})
class App extends Component {
static propTypes = {
hello: PropTypes.string,
world: PropTypes.string,
};
render() {
const { hello, world } = this.props;
return (
<h1>{hello} {world}</h1>
);
}
}
With methods
:
@Wormhole.connect({
counter: 1,
increase(ev) {
ev.preventDefault();
this.counter.set(this.counter.get() + 1);
},
})
class App extends Component {
static propTypes = {
counter: PropTypes.number,
increase: PropTypes.func,
};
render() {
const { counter, increase } = this.props;
return (
<div>
<p>{counter}</p>
<button onClick={increase} />
</div>
);
}
}
static <Provider wormholes />
Makes the wormholes
available to the connect() calls in the component hierarchy below. It's useful when using server-side rendering. See below example for detail.
Props
- wormholes (Object): A key/value object of
wormholes
. - children (ReactElement): The root of your component hierarchy.
Example
import React from 'react';
import ReactDOM from 'react-dom';
import Wormhole, { Provider } from 'react-wormhole-hoc';
import MyRootComponent from './MyRootComponent';
@Wormhole.connect((wormholes) => ({ // `wormholes` is provided by `<Provider>`.
page: wormholes.page
}))
class App extends Component {
static propTypes = {
page: PropTypes.object,
};
render() {
const { page } = this.props;
return (
<div>{page}</div>
);
}
}
const MyRootComponent = () => (<App />);
const wormholes = {
page: {},
isFetching: false,
errorMessage: '',
};
ReactDOM.render(
<Provider wormholes={wormholes}>
<MyRootComponent />
</Provider>,
rootEl,
);
Return
(Function): A HOC creator function.
Installing
Using npm:
npm install --save react-wormhole-hoc
Using yarn:
yarn add react-wormhole-hoc
Dependencies
react-wormhole-hoc
has very few dependencies and most are managed by NPM automatically.
However the following peer dependencies must be specified by your project in order to avoid version conflicts:
react
,
react-addons-shallow-compare
, and
NPM will not automatically install these for you but it will show you a warning message with instructions on how to install them.
Related Projects
License
MIT © Cap32