React Redux Firebase:firebaseConnect发生错误-无法读取未定义属性“有序”

时间:2019-04-30 06:03:30

标签: firebase redux react-redux-firebase

我遵循了 v2.0.0>自述>加载数据(侦听器在装载/卸载时自动进行管理)下的the example in the documentation(无法建立直接链接)。 并用示例1中此处显示的特定于Firestore的连接代替了connect调用](http://react-redux-firebase.com/docs/firestore.html#examples)。

我将Todo示例完全复制到为测试目的而创建的新组件中。

Todo组件:

import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { firebaseConnect,firestoreConnect, 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]}/>
          )
        )
  return (
    <div>
      <h1>Todos</h1>
      <ul>
        {todosList}
      </ul>
      <input type="text" ref="newTodo" />
      <button onClick={this.handleAdd}>
        Add
      </button>
    </div>
  )
}

// export default compose(
//   firestoreConnect([
//     'todos' // { path: '/todos' } // object notation
//   ]),
//   connect((state) => ({
//     todos: state.firestore.data.todos,
//     profile: state.firestore.profile // load profile
//   }))
// )(Todos)





export default compose(
 firestoreConnect(['todos']), // or { collection: 'todos' }
 connect((state, props) => ({
   todos: state.firestore.ordered.todos
 }))
)(Todos)

商店配置已按here in the docs所示进行配置。存储配置经过修改后可以插入由react-boilerplate创建的框架中。

/**
 * Create the store with dynamic reducers
 */

import { createStore, applyMiddleware, compose } from 'redux'
import { fromJS } from 'immutable'
import { routerMiddleware } from 'connected-react-router/immutable'
import createSagaMiddleware from 'redux-saga'
import { reactReduxFirebase, firebaseReducer } from 'react-redux-firebase'
import { reduxFirestore, firestoreReducer } from 'redux-firestore'
import firebase from 'firebase/app' 
import 'firebase/auth'
import 'firebase/database'
import 'firebase/firestore'

import createReducer from './reducers'

const sagaMiddleware = createSagaMiddleware()
const firebaseConfig = {
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.AUTH_DOMAIN,
  databaseURL: process.env.DATABASE_URL,
  projectId: process.env.PROJECT_ID,
  storageBucket: process.env.STORAGE_BUCKET,
  messagingSenderId: process.env.MESSAGING_SENDER_ID,
}
const rrfConfig = {
  userProfile: 'users',
  // useFirestoreForProfile: true, // Firestore for Profile instead of Realtime DB
  // attachAuthIsReady: true
}

// Initialize Cloud Firestore through Firebase
export default function configureStore(initialState = {}, history) {
  firebase.initializeApp(firebaseConfig)

  // Initialize Firestore with timeshot settings
  firebase.firestore()
  // firebase.firestore().settings({ timestampsInSnapshots: true })

  // Create the store with two middlewares
  // 1. sagaMiddleware: Makes redux-sagas work
  // 2. routerMiddleware: Syncs the location/URL path to the state
  const middlewares = [sagaMiddleware, routerMiddleware(history)]

  const enhancers = [
    applyMiddleware(...middlewares),
    // reactReduxFirebase(config), // enhancing our store with these packages
    // reduxFirestore(config)
  ]

  // If Redux DevTools Extension is installed use it, otherwise use Redux compose
  /* eslint-disable no-underscore-dangle, indent */
  const composeEnhancers =
    process.env.NODE_ENV !== 'production' &&
    typeof window === 'object' &&
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
      ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
      : compose
  /* eslint-enable */
  const createStoreWithFirebase = compose(
    reactReduxFirebase(firebase, rrfConfig), // firebase instance as first argument
    reduxFirestore(firebase),
  )(createStore)

  const store = createStoreWithFirebase(
    createReducer(),
    fromJS(initialState),

    composeEnhancers(...enhancers),
  )

  // Extensions
  store.runSaga = sagaMiddleware.run
  store.injectedReducers = {} // Reducer registry
  store.injectedSagas = {} // Saga registry

  // Make reducers hot reloadable, see http://mxs.is/googmo
  /* istanbul ignore next */
  if (module.hot) {
    module.hot.accept('./reducers', () => {
      store.replaceReducer(createReducer(store.injectedReducers))
    })
  }

  return store
}


我完全跟踪并验证了商店配置,以确保在配置中正确配置了文档中介绍的所有步骤。

我的createReducer函数位于单独的文件中,您可以看到我正确添加了firebaseReducerfirebaseReducer



import { combineReducers } from 'redux-immutable'
import { connectRouter } from 'connected-react-router/immutable'
import { firebaseReducer } from 'react-redux-firebase'
import { firestoreReducer } from 'redux-firestore'
import history from 'utils/history'
import languageProviderReducer from 'containers/LanguageProvider/reducer'

export default function createReducer(injectedReducers = {}) {
  const rootReducer = combineReducers({
    firebase: firebaseReducer,
    firestore: firestoreReducer,

    language: languageProviderReducer,
    ...injectedReducers,
  })

  // Wrap the root reducer and return a new root reducer with router state
  const mergeWithRouterState = connectRouter(history)
  return mergeWithRouterState(rootReducer)
}

我的redux存储包含firestorefirebase,并将其注入组件props中。 无效的是使用connectFirestore HoC自动检索文档列表并将其注入到组件中。

这是错误消息:

react-dom.development.js?61bb:20266 Uncaught TypeError: Cannot read property 'ordered' of undefined
    at Function.eval [as mapToProps] (index.js?d834:49)
    at mapToPropsProxy (wrapMapToProps.js?1817:54)
    at Function.detectFactoryAndVerify (wrapMapToProps.js?1817:63)
    at mapToPropsProxy (wrapMapToProps.js?1817:54)
    at handleFirstCall (selectorFactory.js?805c:37)
    at pureFinalPropsSelector (selectorFactory.js?805c:85)
    at Object.runComponentSelector [as run] (connectAdvanced.js?48b8:43)
    at Connect.initSelector (connectAdvanced.js?48b8:195)
    at new Connect (connectAdvanced.js?48b8:136)
    at constructClassInstance (react-dom.development.js?61bb:11315)

(从我的代码中摘录为示例1 in documentation):

export default compose(
 firestoreConnect(['todos']), // or { collection: 'todos' }
 connect((state, props) => ({
   todos: state.firestore.ordered.todos
 }))
)(Todos)

我检查了state变量,它确实包含firestore属性。该属性包含预期的功能,但是缺少“ ordered”(未定义)下的查询结果。

我尝试了所有不同的方式来使用firestoreconnect,例如使用基于类的组件,使用带有参数的查询等,都给出相同的错误。

我的Firebase项目配置正确,因为我能够在集合中创建文档。一个todos集合用于测试目的,其中包含2个文档。

我遇到过this post,其中提到以下内容:

  

如果您刚刚升级到React-Redux v6,那是因为react-redux-firebase与v6不兼容。

     

有关详细信息,请参见https://github.com/prescottprue/react-redux-firebase/issues/581

这不适用于我,因为我正在使用react-redux版本5。这是我正在使用的版本:

    "firebase": "^5.10.1",
    "react-redux": "^5.0.7",
    "react-redux-firebase": "^2.2.6",
    "redux": "^4.0.1",
    "redux-firestore": "^0.7.3",

我在此上花费了大量时间。就像我说的那样,使用firestore将新数据添加到集合中可以很好地工作。无论我如何解决该问题,就是这个HoC业务失败了。 任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

从来没有解决过这个问题。我想这与不兼容的版本有关。我最终要做的是下载react-boilerplate的v4,并设置v3 react-redux-firebase,它使用Context API而不是商店增强器。现在效果很好。