redux-devshare
Version:
[![NPM version][npm-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Code Climate][climate-image]][climate-url] [![Code Coverage][coverage-i
95 lines (81 loc) • 3.06 kB
JavaScript
import React, { PropTypes, Component } from 'react'
import { isEqual } from 'lodash'
import { watchEvents, unWatchEvents } from './actions/query'
import { getEventsFromInput, createCallable } from './utils'
/**
* @name devshareConnect
* @extends React.Component
* @description Higher Order Component that automatically listens/unListens
* to provided devshare paths using React's Lifecycle hooks.
* @param {Array} watchArray - Array of objects or strings for paths to sync from Firebase
* @return {Function} - that accepts a component to wrap and returns the wrapped component
* @example <caption>Basic</caption>
* // this.props.devshare set on App component as devshare object with helpers
* import { devshareConnect } from 'react-redux-devshare'
* export default devshareConnect()(App)
* @example <caption>Data</caption>
* import { connect } from 'react-redux'
* import { devshareConnect, dataToJS } from 'redux-devshare'
*
* // sync /todos from devshare into redux
* const fbWrapped = devshareConnect([
* 'todos'
* ])(App)
*
* // pass todos list from redux as this.props.todosList
* export default connect(({ devshare }) => ({
* todosList: dataToJS(devshare, 'todos'),
* profile: pathToJS(devshare, 'profile'), // pass profile data as this.props.proifle
* auth: pathToJS(devshare, 'auth') // pass auth data as this.props.auth
* }))(fbWrapped)
*/
export default (dataOrFn = []) => WrappedComponent => {
class DevshareConnect extends Component {
constructor (props, context) {
super(props, context)
this._devshareEvents = []
this.devshare = null
}
static contextTypes = {
store: PropTypes.object.isRequired
};
componentWillMount () {
const { devshare, dispatch } = this.context.store
// Allow function to be passed
const inputAsFunc = createCallable(dataOrFn)
this.prevData = inputAsFunc(this.props, devshare)
this.devshare = devshare
this._devshareEvents = getEventsFromInput(this.prevData)
watchEvents(devshare, dispatch, this._devshareEvents)
}
componentWillUnmount () {
const { devshare, dispatch } = this.context.store
unWatchEvents(devshare, dispatch, this._devshareEvents)
}
componentWillReceiveProps (np) {
const { devshare, dispatch } = this.context.store
const inputAsFunc = createCallable(dataOrFn)
const data = inputAsFunc(np, devshare)
// Handle a data parameter having changed
if (!isEqual(data, this.prevData)) {
this.prevData = data
// UnWatch all current events
unWatchEvents(devshare, dispatch, this._devshareEvents)
// Get watch events from new data
this._devshareEvents = getEventsFromInput(data)
// Watch new events
watchEvents(devshare, dispatch, this._devshareEvents)
}
}
render () {
return (
<WrappedComponent
{...this.props}
{...this.state}
devshare={this.devshare}
/>
)
}
}
return DevshareConnect
}