Skip to content

Commit

Permalink
v3.0.0-alpha.3 (#595)
Browse files Browse the repository at this point in the history
* fix(firestoreConnect): remove remaining usage of old context pattern - #594
* fix(HOCs): add displayName to `firebaseConnect` and `firestoreConnect`
  • Loading branch information
prescottprue committed Dec 18, 2018
1 parent 1e96425 commit 71dee92
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"presets": [
"minify",
["minify", { "keepFnName": true }],
"@babel/preset-react",
["@babel/env", {
"targets": {
Expand Down
80 changes: 42 additions & 38 deletions examples/complete/simple/src/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,50 @@ import TodoItem from './TodoItem'
import './App.css'
import NewTodo from './NewTodo';

const Home = ({ firebase, todos }) => (
<div className='App'>
<div className='App-header'>
<h2>react-redux-firebase demo</h2>
<img src={logo} className='App-logo' alt='logo' />
function Home({ firebase, todos }) {
return (
<div className='App'>
<div className='App-header'>
<h2>react-redux-firebase demo</h2>
<img src={logo} className='App-logo' alt='logo' />
</div>
<div className='App-todos'>
<h4>
Loaded From
<span className='App-Url'>
<a href='https://redux-firebasev3.firebaseio.com/'>
redux-firebasev3.firebaseio.com
</a>
</span>
</h4>
<h4>Todos List</h4>
{
!isLoaded(todos)
? 'Loading'
: isEmpty(todos)
? 'Todo list is empty'
: todos.reverse().map(({ value: todo, key }, ind) => (
<TodoItem
key={`${key}-${ind}`}
id={key}
{...todo}
/>
))
}
<NewTodo />
</div>
</div>
<div className='App-todos'>
<h4>
Loaded From
<span className='App-Url'>
<a href='https://redux-firebasev3.firebaseio.com/'>
redux-firebasev3.firebaseio.com
</a>
</span>
</h4>
<h4>Todos List</h4>
{
!isLoaded(todos)
? 'Loading'
: isEmpty(todos)
? 'Todo list is empty'
: todos.reverse().map(({ value: todo, key }, ind) => (
<TodoItem
key={`${key}-${ind}`}
id={key}
{...todo}
/>
))
}
<NewTodo />
</div>
</div>
)
)
}

Home.propTypes = {
// firebase: PropTypes.object.isRequired
firebase: PropTypes.object.isRequired
}

function mapStateToProps(state) {
return {
todos: state.firebase.ordered.todos
}
}

const enhance = compose(
Expand All @@ -57,11 +65,7 @@ const enhance = compose(
queryParams: ['limitToLast=10']
}
]),
connect(
({ firebase }) => ({
todos: firebase.ordered.todos,
})
)
connect(mapStateToProps)
)

export default enhance(Home)
3 changes: 1 addition & 2 deletions examples/complete/simple/src/TodoItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ const enhance = compose(
})
)

const TodoItem = (props) => {
function TodoItem(props) {
const { deleteTodo, toggleDone, text, name, done } = props
console.log('props', props)
return (
<li className="Todo">
<input
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-redux-firebase",
"version": "3.0.0-alpha.2",
"version": "3.0.0-alpha.3",
"description": "Redux integration for Firebase. Comes with a Higher Order Components for use with React.",
"main": "lib/index.js",
"module": "es/index.js",
Expand Down
2 changes: 1 addition & 1 deletion src/ReactReduxFirebaseProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import createFirebaseInstance from './createFirebaseInstance'
import ReactReduxFirebaseContext from './ReactReduxFirebaseContext'
import ReduxFirestoreProvider from './ReduxFirestoreProvider'

const ReactReduxFirebaseProvider = (props = {}) => {
function ReactReduxFirebaseProvider(props = {}) {
const {
children,
config,
Expand Down
2 changes: 1 addition & 1 deletion src/ReduxFirestoreProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import ReduxFirestoreContext from './ReduxFirestoreContext'

const ReduxFirestoreProvider = (props = {}) => {
function ReduxFirestoreProvider(props = {}) {
const {
children,
config,
Expand Down
18 changes: 11 additions & 7 deletions src/firebaseConnect.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import { isEqual, differenceWith } from 'lodash'
import hoistStatics from 'hoist-non-react-statics'
import { watchEvents, unWatchEvents } from './actions/query'
import { getEventsFromInput, createCallable, getDisplayName } from './utils'
import { getEventsFromInput, createCallable, wrapDisplayName } from './utils'
import ReactReduxFirebaseContext from './ReactReduxFirebaseContext'

/**
Expand All @@ -28,14 +28,17 @@ export const createFirebaseConnect = (storeKey = 'store') => (
dataOrFn = []
) => WrappedComponent => {
class FirebaseConnectWrapped extends Component {
static displayName = `FirebaseConnect(${getDisplayName(WrappedComponent)})`
static displayName = wrapDisplayName(
WrappedComponent,
'FirebaseConnectWrapped'
)
static wrappedComponent = WrappedComponent

firebaseEvents = []
firebase = null
prevData = null

componentWillMount() {
componentDidMount() {
const { firebase, dispatch } = this.props

// Allow function to be passed
Expand Down Expand Up @@ -87,7 +90,7 @@ export const createFirebaseConnect = (storeKey = 'store') => (

FirebaseConnectWrapped.propTypes = {
dispatch: PropTypes.func.isRequired,
firebase: PropTypes.object
firebase: PropTypes.object.isRequired
}

const HoistedComp = hoistStatics(FirebaseConnectWrapped, WrappedComponent)
Expand All @@ -104,9 +107,10 @@ export const createFirebaseConnect = (storeKey = 'store') => (
</ReactReduxFirebaseContext.Consumer>
)

FirebaseConnect.propTypes = {
dispatch: PropTypes.func.isRequired
}
FirebaseConnect.displayName = wrapDisplayName(
WrappedComponent,
'FirebaseConnect'
)

return FirebaseConnect
}
Expand Down
37 changes: 20 additions & 17 deletions src/firestoreConnect.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import ReduxFirestoreContext from './ReduxFirestoreContext'
* Firebase state (state.firebase)
* @return {Function} - HOC that accepts a watchArray and wraps a component
* @example <caption>Basic</caption>
* // this.props.firebase set on App component as firebase object with helpers
* // props.firebase set on App component as firebase object with helpers
* import { createFirestoreConnect } from 'react-redux-firebase'
* // create firebase connect that uses another redux store
* const firestoreConnect = createFirestoreConnect('anotherStore')
Expand All @@ -28,7 +28,10 @@ export const createFirestoreConnect = (storeKey = 'store') => (
) => WrappedComponent => {
class FirestoreConnectWrapped extends Component {
static wrappedComponent = WrappedComponent
static displayName = wrapDisplayName(WrappedComponent, 'FirestoreConnect')
static displayName = wrapDisplayName(
WrappedComponent,
'FirestoreConnectWrapped'
)

prevData = null

Expand All @@ -37,20 +40,18 @@ export const createFirestoreConnect = (storeKey = 'store') => (
}

componentDidMount() {
const { firestore } = this.store
if (this.firestoreIsEnabled) {
// Allow function to be passed
// Listener configs as object (handling function being passed)
const inputAsFunc = createCallable(dataOrFn)
this.prevData = inputAsFunc(this.props, this.props)

firestore.setListeners(this.prevData)
// Attach listeners based on listener config
this.props.firestore.setListeners(this.prevData)
}
}

componentDidUnmount() {
const { firestore } = this.store
componentWillUnmount() {
if (this.firestoreIsEnabled && this.prevData) {
firestore.unsetListeners(this.prevData)
this.props.firestore.unsetListeners(this.prevData)
}
}

Expand All @@ -59,7 +60,7 @@ export const createFirestoreConnect = (storeKey = 'store') => (
const inputAsFunc = createCallable(dataOrFn)
const data = inputAsFunc(np, this.props)

// Handle changes to data
// Check for changes in the listener configs
if (this.firestoreIsEnabled && !isEqual(data, this.prevData)) {
const changes = this.getChanges(data, this.prevData)

Expand All @@ -86,7 +87,7 @@ export const createFirestoreConnect = (storeKey = 'store') => (
}

FirestoreConnectWrapped.propTypes = {
dispatch: PropTypes.func.isRequired,
dispatch: PropTypes.func,
firebase: PropTypes.object,
firestore: PropTypes.object
}
Expand All @@ -98,6 +99,10 @@ export const createFirestoreConnect = (storeKey = 'store') => (
{firestore => <HoistedComp firestore={firestore} {...props} />}
</ReduxFirestoreContext.Consumer>
)
FirestoreConnect.displayName = wrapDisplayName(
WrappedComponent,
'FirestoreConnect'
)

FirestoreConnect.propTypes = {
dispatch: PropTypes.func.isRequired
Expand All @@ -118,20 +123,18 @@ export const createFirestoreConnect = (storeKey = 'store') => (
* is passed the current props and the firebase object.
* @return {Function} - that accepts a component to wrap and returns the wrapped component
* @example <caption>Basic</caption>
* // this.props.firebase set on App component as firebase object with helpers
* // props.firebase set on App component as firebase object with helpers
* import { firestoreConnect } from 'react-redux-firebase'
* export default firestoreConnect()(SomeComponent)
* @example <caption>Basic</caption>
* import { connect } from 'react-redux'
* import { firestoreConnect } from 'react-redux-firebase'
*
* // pass todos list from redux as this.props.todosList
* // pass todos list from redux as props.todosList
* export default compose(
* firestoreConnect(['todos']), // sync todos collection from Firestore into redux
* firestoreConnect(() => ['todos']), // sync todos collection from Firestore into redux
* connect((state) => ({
* todosList: state.firestore.data.todos,
* profile: state.firestore.profile, // pass profile data as this.props.profile
* auth: state.firestore.auth // pass auth data as this.props.auth
* todosList: state.firestore.data.todos
* })
* )(SomeComponent)
*/
Expand Down
7 changes: 6 additions & 1 deletion src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function createCallable(f) {
return isFunction(f) ? f : () => f
}

export function getDisplayName(Component) {
function getDisplayName(Component) {
if (typeof Component === 'string') {
return Component
}
Expand All @@ -22,6 +22,11 @@ export function getDisplayName(Component) {
return Component.displayName || Component.name || 'Component'
}

/**
* Get provided react component's display name and wrap with with a passed name.
* @param {React.Component} BaseComponent - Component from which to get name to wrap
* @param {String} hocName - Name of wrapping hoc
*/
export function wrapDisplayName(BaseComponent, hocName) {
return `${hocName}(${getDisplayName(BaseComponent)})`
}
Expand Down
38 changes: 23 additions & 15 deletions src/withFirebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import ReactReduxFirebaseContext from './ReactReduxFirebaseContext'
* @return {Function} - Higher Order Component which accepts an array of
* watchers config and wraps a React Component
* @example <caption>Basic</caption>
* // this.props.firebase set on App component as firebase object with helpers
* // props.firebase set on App component as firebase object with helpers
* import { createWithFirebase } from 'react-redux-firebase'
*
* // create withFirebase that uses another redux store
Expand Down Expand Up @@ -68,28 +68,34 @@ export const createWithFirebase = (storeKey = 'store') => WrappedComponent => {
* @example <caption>Basic</caption>
* import { withFirebase } from 'react-redux-firebase'
*
* const AddData = ({ firebase: { push } }) =>
* <div>
* <button onClick={() => push('todos', { done: false, text: 'Sample' })}>
* Add Sample Todo
* </button>
* </div>
* function AddData({ firebase: { push } }) {
* return (
* <div>
* <button onClick={() => push('todos', { done: false, text: 'Sample' })}>
* Add Sample Todo
* </button>
* </div>
* )
* }
*
* export default withFirebase(AddData)
* @example <caption>Within HOC Composition</caption>
* import { compose } from 'redux' // can also come from recompose
* import { withHandlers } from 'recompose'
* import { withFirebase } from 'react-redux-firebase'
*
* const AddTodo = ({ addTodo }) =>
* <div>
* <button onClick={addTodo}>
* Add Sample Todo
* </button>
* </div>
* function AddTodo({ addTodo }) {
* return (
* <div>
* <button onClick={addTodo}>
* Add Sample Todo
* </button>
* </div>
* )
* }
*
* export default compose(
* withFirebase(AddTodo),
* const enhance = compose(
* withFirebase,
* withHandlers({
* addTodo: props => () =>
* props.firestore.add(
Expand All @@ -98,5 +104,7 @@ export const createWithFirebase = (storeKey = 'store') => WrappedComponent => {
* )
* })
* )
*
* export default enhance(AddTodo)
*/
export default createWithFirebase()

0 comments on commit 71dee92

Please sign in to comment.