useSelector 不起作用,除非显式导入存储



我在盖茨比.js应用程序中遇到useSelector钩子的问题。钩子无法到达 redux 的store,除非store从 redux 安装文件中显式导出并导入到组件文件中。似乎<Provider>不可用(?

错误:选择存储状态时出错:无法读取未定义的属性"user">

我想我有点搞砸了 redux 设置或盖茨比浏览器//ssr 设置,但我不知道具体如何......任何帮助将不胜感激。

// App.js
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { store } from '../store/ReduxWrapper' // <-- store needs to be imported to be accessible ?!
import { loadFirebaseInitialize } from '../store/app'
import AuthenticatedApp from '../containers/AuthenticatedApp'
import UnauthenticatedApp from '../containers/UnauthenticatedApp'
const App = () => {
const dispatch = useDispatch()
const firebase = useSelector(store => store.app.firebase) // <-- store is undefined unless explicitely    imported
const user = useSelector(store => store.auth.user) // <-- store is undefined unless explicitely    imported
if (!firebase) {
dispatch(loadFirebaseInitialize())
return (
<div>
<p>Loading firebase</p>
</div>
)
} else {
return user ? <AuthenticatedApp /> : <UnauthenticatedApp />
}
}
export default App

// ReduxWrapper.js
import React from 'react'
import { Provider } from 'react-redux'
import { applyMiddleware, createStore } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from '.';
export const store = createStore(
rootReducer,
applyMiddleware(thunk)
)
export default ({ element }) => (
<Provider store={store}>{element}</Provider>
);

// gatsby-browser.js / gatsby-ssr.js
export { default as wrapRootElement } from './src/store/ReduxWrapper'

编辑:添加更多与 redux 相关的代码:

// index.js
import { combineReducers } from 'redux';
import app from './app';
import auth from './auth';
export default combineReducers({ app, auth });

// auth.js
// to get state from a sibling ('app.js') store
import { store } from '../store/ReduxWrapper' 
const initialState = {
isAuthenticated: false,
isAuthPending: false,
error: null,
user: null,
}
const AUTH_REQUEST_INITIALIZE = 'AUTH_REQUEST_INITIALIZE'
const AUTH_REQUEST_SUCCESS = 'AUTH_REQUEST_SUCCESS'
const AUTH_REQUEST_ERROR = 'AUTH_REQUEST_SUCCESS'
const AUTH_LOGOUT = 'AUTH_LOGOUT'
export const authRequestInitialize = () => ({
type: AUTH_REQUEST_INITIALIZE,
})
export const authRequestSuccess = user => ({
type: AUTH_REQUEST_SUCCESS,
user,
})
export const authRequestError = error => ({
type: AUTH_REQUEST_ERROR,
error,
})
export const authLogin = ({ email, password }) => dispatch => {
const { firebase } = store.getState().app
if (firebase) {
dispatch(authRequestInitialize())
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(user => console.log(`user`, user) || dispatch(authRequestSuccess(user)))
.catch(error => console.log(`authError`, error) || dispatch(authRequestError(error)))
}
}
export const authLogout = () => dispatch => {
const { firebase } = store.getState().app
if (firebase) {
firebase.auth().signOut().then(
res => dispatch({ type: AUTH_LOGOUT })
)  
}
}
export default (state = initialState, action) => {
switch (action.type) {
case AUTH_REQUEST_INITIALIZE:
return { ...state, isAuthPending: true }
case AUTH_REQUEST_SUCCESS:
return { ...state, user: action.user }
case AUTH_REQUEST_ERROR:
return { ...state, error: action.error }
case AUTH_LOGOUT:
return { ...state, user: null }
default:
return state
}
}

//app.js
import getFirebase from '../firebase'
const initialState = {
firebase: null,
isFirebaseLoading: false,
}
const LOAD_FIREBASE_INITIALIZE = 'LOAD_FIREBASE_INITIALIZE'
const LOAD_FIREBASE_SUCCESS = 'LOAD_FIREBASE_SUCCESS'
const LOAD_FIREBASE_ERROR = 'LOAD_FIREBASE_ERROR'
export const loadFirebaseInitialize = () => {
return dispatch => {
const app = import('firebase/app')
const auth = import('firebase/auth')
const firestore = import('firebase/firestore')
Promise.all([app, auth, firestore])
.then(values => {
const firebase = getFirebase(values[0])
dispatch(loadFirebaseSuccess(firebase))
})
.catch(error => dispatch(loadFirebaseError(error)))
}
}
export const loadFirebaseSuccess = firebaseObj => ({
type: LOAD_FIREBASE_SUCCESS,
firebaseObj,
})
export const loadFirebaseError = error => ({
type: LOAD_FIREBASE_ERROR,
error,
})
export default (state = initialState, action) => {
switch (action.type) {
case LOAD_FIREBASE_INITIALIZE:
return { ...state, isFirebaseLoading: true }
case LOAD_FIREBASE_SUCCESS:
return {
...state,
isFirebaseLoading: false,
firebase: action.firebaseObj,
}
case LOAD_FIREBASE_ERROR:
return { ...state, isFirebaseLoading: false, error: action.error }
default:
return state
}
}

正如我所看到的,你不使用此代码:

export default ({ element }) => (
<Provider store={store}>{element}</Provider>
);

将您的应用程序包装在此中,您可以访问商店,现在该应用程序无法访问商店。

正如我发现的那样,上述问题可能是由 gatsby 开发环境中的错误引起的——使用 git bash 而不是 windows 命令行似乎可以解决它(以及其他问题,例如反应钩子无法正常工作(。

相关内容

最新更新