Skip to content

Commit

Permalink
v3.0.0-alpha (#566)
Browse files Browse the repository at this point in the history
* feat(HOCs): switch `firestoreConnect` and `firebaseConnect` to use `componentDidMount` over `componentWillMount` - #564 
* feat(core): New react context API working with HOCs (`firebaseConnect`, `firestoreConnect` `withFirebase`, and `withFirestore`) - #581
* feat(core): support `react-redux` v6 by removing usage of `context.store` (used to be added by `Provider` from `react-redux`)
* feat(core): Added `ReactReduxFirebaseContext` and `ReduxFirestoreContext` (with associated providers `ReactReduxFirebaseProvider` `ReduxFirestoreProvider` respectively)
* fix(core): shrink build sizes considerably by adding `babel-preset-minify` - #573
* feat(deps): update `hoist-non-react-statics` to `^3.1.0`
* feat(deps): upgrade to `babel^7`
* feat(deps): Update to `webpack^4` (along with `webpack-cli`)
* feat(deps): update react peer dependency to `^16.4` for new Context API (matches `react-redux`)
  • Loading branch information
prescottprue authored Dec 15, 2018
1 parent 34b8f08 commit f91ed93
Show file tree
Hide file tree
Showing 57 changed files with 26,019 additions and 4,745 deletions.
14 changes: 6 additions & 8 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"presets": [
"react",
["env", {
"minify",
"@babel/preset-react",
["@babel/env", {
"targets": {
"chrome": 52,
"browsers": ["last 2 versions", "safari >= 7"]
Expand All @@ -11,10 +12,7 @@
"plugins": [
"lodash",
"add-module-exports",
"transform-object-rest-spread",
"transform-object-assign",
"transform-class-properties",
"transform-export-extensions"
"@babel/plugin-proposal-class-properties"
],
"env": {
"es": {
Expand All @@ -25,8 +23,8 @@
},
"test": {
"plugins": [
"transform-runtime",
"transform-async-to-generator",
"@babel/plugin-transform-runtime",
"@babel/transform-async-to-generator",
["module-resolver", {
"root": ["./src"]
}]
Expand Down
176 changes: 100 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@ Include `reactReduxFirebase` (store enhancer) and `firebaseReducer` (reducer) w
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore, combineReducers, compose } from 'redux'
import { reactReduxFirebase, firebaseReducer } from 'react-redux-firebase'
import firebase from 'firebase'
// import { reduxFirestore, firestoreReducer } from 'redux-firestore' // <- needed if using firestore
import firebase from 'firebase/app'
import 'firebase/auth'
// import 'firebase/firestore' // <- needed if using firestore
// import 'firebase/functions' // <- needed if using httpsCallable
import { createStore, combineReducers, compose } from 'redux'
import { ReactReduxFirebaseProvider, firebaseReducer } from 'react-redux-firebase'
// import { createFirestoreInstance, firestoreReducer } from 'redux-firestore' // <- needed if using firestore

const firebaseConfig = {}

Expand All @@ -70,12 +71,6 @@ firebase.initializeApp(firebaseConfig)
// firebase.firestore() // <- needed if using firestore
// firebase.functions() // <- needed if using httpsCallable

// Add reactReduxFirebase enhancer when making store creator
const createStoreWithFirebase = compose(
reactReduxFirebase(firebase, rrfConfig), // firebase instance as first argument
// reduxFirestore(firebase) // <- needed if using firestore
)(createStore)

// Add firebase to reducers
const rootReducer = combineReducers({
firebase: firebaseReducer,
Expand All @@ -84,12 +79,21 @@ const rootReducer = combineReducers({

// Create store with reducers and initial state
const initialState = {}
const store = createStoreWithFirebase(rootReducer, initialState)
const store = createStore(rootReducer, initialState)

const rrfProps = {
firebase,
config: rrfConfig,
dispatch: store.dispatch,
// createFirestoreInstance // <- needed if using firestore
}

// Setup react-redux so that connect HOC can be used
const App = () => (
<Provider store={store}>
<Todos />
<ReactReduxFirebaseProvider {...rrfProps}>
<Todos />
</ReactReduxFirebaseProvider>
</Provider>
);

Expand All @@ -104,26 +108,30 @@ The Firebase instance can then be grabbed from context within your components (`
import React from 'react'
import PropTypes from 'prop-types'
import { withFirebase } from 'react-redux-firebase'
import { compose, withHandlers } from 'recompose'

const Todos = ({ firebase }) => {
const sampleTodo = { text: 'Sample', done: false }
const pushSample = () => firebase.push('todos', sampleTodo)
function Todos({ firebase, addSampleTodo }) {
return (
<div>
<h1>Todos</h1>
<ul>
{todosList}
</ul>
<input type="text" ref="newTodo" />
<button onClick={pushSample}>
<h1>New Sample Todo</h1>
<button onClick={addSampleTodo}>
Add
</button>
</div>
)
}

export default withFirebase(Todos)
// or firebaseConnect()(Todos)
const enhance = compose(
withFirebase,
withHandlers({
addSampleTodo: props => () => {
const sampleTodo = { text: 'Sample', done: false }
return props.firebase.push('todos', sampleTodo)
}
})
)

export default enhance(Todos)
```

**Load Data (listeners automatically managed on mount/unmount)**
Expand All @@ -135,33 +143,30 @@ import { connect } from 'react-redux'
import { compose } from 'redux'
import { firebaseConnect, isLoaded, isEmpty } from 'react-redux-firebase'

const Todos = ({ todos, firebase }) => {
// Build Todos list if todos exist and are loaded
const todosList = !isLoaded(todos)
? 'Loading'
: isEmpty(todos)
? 'Todo list is empty'
: Object.keys(todos).map(
(key, id) => (
<TodoItem key={key} id={id} todo={todos[key]}/>
)
)
function Todos({ todos, firebase }) {
if (!isLoaded(todos)) {
return <div>Loading...</div>
}
if (isEmpty(todos)) {
return <div>Todos List Is Empty</div>
}
return (
<div>
<h1>Todos</h1>
<ul>
{todosList}
{
Object.keys(todos).map(
(key, id) => (
<TodoItem key={key} id={id} todo={todos[key]}/>
)
)
}
</ul>
<input type="text" ref="newTodo" />
<button onClick={this.handleAdd}>
Add
</button>
</div>
)
}

export default compose(
firebaseConnect([
firebaseConnect(() => [
'todos' // { path: '/todos' } // object notation
]),
connect((state) => ({
Expand All @@ -179,8 +184,8 @@ It is common to make a detail page that loads a single item instead of a whole l
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { firebaseConnect, getVal } from 'react-redux-firebase'
import { compose, withHandlers } from 'recompose'

// Component enhancer that loads todo into redux then into the todo prop
const enhance = compose(
Expand All @@ -193,21 +198,27 @@ const enhance = compose(
}),
connect(({ firebase }, props) => ({
todo: getVal(firebase, `data/todos/${props.params.todoId}`), // lodash's get can also be used
}))
})),
withHandlers({
updateTodo: props => () => {
return firebase.update(`todos/${params.todoId}`, { done: !todo.isDone })
}
})
)

const Todo = ({ todo, firebase, params }) =>
<div>
<input
name="isDone"
type="checkbox"
checked={todo.isDone}
onChange={() =>
firebase.update(`todos/${params.todoId}`, { done: !todo.isDone })
}
/>
<span>{todo.label}</span>
</div>
function Todo({ todo }) {
return (
<div>
<input
name="isDone"
type="checkbox"
checked={todo.isDone}
onChange={updateTodo}
/>
<span>{todo.label}</span>
</div>
)
}

// Export enhanced component
export default enhance(Todo)
Expand All @@ -223,21 +234,38 @@ import { connect } from 'react-redux'
import { compose } from 'redux'
import { withFirebase, isLoaded, isEmpty } from 'react-redux-firebase'

const Todos = ({ firebase }) => {
// Build Todos list if todos exist and are loaded
const todosList = !isLoaded(todos)
? 'Loading'
: isEmpty(todos)
? 'Todo list is empty'
: Object.keys(todos).map(
(key, id) => <TodoItem key={key} id={id} todo={todos[key]}/>
function TodosList({ todos }) {
if (!isLoaded(todos)) {
return <div>Loading...</div>
}
if (isEmpty(todos)) {
return <div>Todos List Is Empty</div>
}
return (
<ul>
{
Object.keys(todos).map((key, id) =>
<TodoItem key={key} id={id} todo={todos[key]}/>
)
}
</ul>
)
}
const withTodosData = compose(
withFirebase, // or firebaseConnect()
connect((state) => ({
todos: state.firebase.data.todos,
// profile: state.firebase.profile // load profile
}))
)

const EnhancedTodosList = withTodosData(TodosList)

function Todos({ firebase }) {
return (
<div>
<h1>Todos</h1>
<ul>
{todosList}
</ul>
<EnhancedTodosList />
<button onClick={() => firebase.watchEvent('value', 'todos')}>
Load Todos
</button>
Expand All @@ -246,13 +274,7 @@ const Todos = ({ firebase }) => {
}

// Export enhanced component
export default compose(
withFirebase, // or firebaseConnect()
connect((state) => ({
todos: state.firebase.data.todos,
// profile: state.firebase.profile // load profile
}))
)(Todos)
export default withFirebase(Todos)
```

## Firestore
Expand Down Expand Up @@ -336,13 +358,15 @@ Please visit the [FAQ section of the docs](http://docs.react-redux-firebase.com/

Most commonly people consume Redux Firestore as a [CommonJS module](http://webpack.github.io/docs/commonjs.html). This module is what you get when you import redux in a Webpack, Browserify, or a Node environment.

If you don't use a module bundler, it's also fine. The redux-firestore npm package includes precompiled production and development [UMD builds](https://github.com/umdjs/umd) in the [dist folder](https://unpkg.com/redux-firestore@latest/dist/). They can be used directly without a bundler and are thus compatible with many popular JavaScript module loaders and environments. For example, you can drop a UMD build as a `<script>` tag on the page. The UMD builds make Redux Firestore available as a `window.ReduxFirestore` global variable.
If you don't use a module bundler, it's also fine. The redux-firestore npm package includes precompiled production and development [UMD builds](https://github.com/umdjs/umd) in the [dist folder](https://unpkg.com/redux-firestore@latest/dist/). They can be used directly without a bundler and are thus compatible with many popular JavaScript module loaders and environments. For example, you can drop a UMD build as a `<script>` tag on the page. The UMD builds make Redux Firestore available as a `window.ReactReduxFirebase` global variable.

It can be imported like so:

```html
<script src="../node_modules/react-redux-firebase/dist/react-redux-firebase.min.js"></script>
<script src="../node_modules/redux-firestore/dist/redux-firestore.min.js"></script>
<!-- or through cdn: <script src="https://unpkg.com/react-redux-firebase@latest/dist/react-redux-firebase.min.js"></script> -->
<!-- or through cdn: <script src="https://unpkg.com/redux-firestore@latest/dist/redux-firestore.min.js"></script> -->
<script>console.log('react redux firebase:', window.ReactReduxFirebase)</script>
```

Expand All @@ -365,8 +389,8 @@ Thank you to all our backers! 🙏
[npm-downloads-image]: https://img.shields.io/npm/dm/react-redux-firebase.svg?style=flat-square
[quality-image]: http://npm.packagequality.com/shield/react-redux-firebase.svg?style=flat-square
[quality-url]: https://packagequality.com/#?package=react-redux-firebase
[backers]:https://opencollective.com/react-redux-firebase/backers/badge.svg?style=flat-square&color=blue
[become-a-backer]:https://opencollective.com/react-redux-firebase#backer
[backers]: https://opencollective.com/react-redux-firebase/backers/badge.svg?style=flat-square&color=blue
[become-a-backer]: https://opencollective.com/react-redux-firebase#backer
[travis-image]: https://img.shields.io/travis/prescottprue/react-redux-firebase/master.svg?style=flat-square
[travis-url]: https://travis-ci.org/prescottprue/react-redux-firebase
[daviddm-image]: https://img.shields.io/david/prescottprue/react-redux-firebase.svg?style=flat-square
Expand Down
5 changes: 3 additions & 2 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

* [Read Me](/README.md)
* [Getting Started](/docs/getting_started.md)
* [v2 Migration Guide](/docs/v2-migration-guide.md)
* [Auth](/docs/auth.md)
* [Queries](/docs/queries.md)
* [Firestore](/docs/firestore.md)
Expand Down Expand Up @@ -43,11 +42,13 @@
* [listenersReducer](/docs/api/reducers.md#listenersreducer)
* [dataReducer](/docs/api/reducers.md#datareducer)
* [orderedReducer](/docs/api/reducers.md#orderedreducer)
* [reactReduxFirebase](/docs/api/enhancer.md)
* [props.firebase](/docs/api/props-firebase.md)
* [getFirebase](/docs/api/get-firebase.md)
* [firebaseInstance](/docs/api/firebaseInstance.md)
* [helpers](/docs/api/helpers.md)
* Migration Guides
* [v3 Migration Guide](/docs/v3-migration-guide.md)
* [v2 Migration Guide](/docs/v2-migration-guide.md)
* [FAQ](/docs/FAQ.md)
* [Roadmap](/docs/roadmap.md)
* [Contributing](/docs/contributing.md)
4 changes: 0 additions & 4 deletions bin/api-docs-generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ const files = [
src: 'createFirebaseInstance.js',
dest: 'firebaseInstance.md'
},
{
src: 'enhancer.js',
dest: 'enhancer.md'
},
{
src: 'helpers.js',
dest: 'helpers.md'
Expand Down
1 change: 0 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
* [listenersReducer](/docs/api/reducers.md#listenersreducer)
* [dataReducer](/docs/api/reducers.md#datareducer)
* [orderedReducer](/docs/api/reducers.md#orderedreducer)
* [reactReduxFirebase](/docs/api/enhancer.md)
* [props.firebase](/docs/api/props-firebase.md)
* [getFirebase](/docs/api/get-firebase.md)
* [firebaseInstance](/docs/api/firebaseInstance.md)
Expand Down
Loading

0 comments on commit f91ed93

Please sign in to comment.