所以我最近开始学习Redux,现在我正在尝试用它制作我的第一个应用程序,但我偶然发现了一个我无法自行解决的问题。基本上我希望用户点击一个按钮(将进行身份验证)并从Firebase获取他或她的所有数据并显示它。
这是我的index.js:
// Dependencies
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import createHistory from 'history/createBrowserHistory';
import { ConnectedRouter, routerReducer, routerMiddleware } from 'react-router-redux';
import ReduxPromise from "redux-promise";
import ReduxThunk from 'redux-thunk';
// Reducers
import rootReducer from './reducers';
// ServiceWorker
import registerServiceWorker from './registerServiceWorker.js';
// Styles
import './styles/index.css';
// Components
import App from './containers/App.js';
const history = createHistory();
const middleware = routerMiddleware(history);
// Create store
const store = createStore(
combineReducers({
...rootReducer,
router: routerReducer
}),
applyMiddleware(ReduxThunk, middleware, ReduxPromise)
)
ReactDOM.render((
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>
), document.getElementById('root'));
registerServiceWorker();
我的主要容器,App.js:
import React, { Component } from 'react';
import { Route, Switch, withRouter } from 'react-router-dom'
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import firebase from 'firebase';
import firebaseConfig from '../firebaseConfig.js';
// Actions
import { fetchAllMonths } from "../actions/index";
// Static components
import Nav from '../components/Nav.js';
// Routes
import CurrentMonth from '../components/CurrentMonth.js';
import AddNewMonth from '../components/AddNewMonth.js';
import Archive from '../components/Archive.js';
import Settings from '../components/Settings.js';
class App extends Component {
constructor (props) {
super(props);
this.login = this.login.bind(this);
}
componentWillMount() {
firebase.initializeApp(firebaseConfig);
firebase.auth().signInAnonymously().catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
});
}
login() {
this.props.fetchAllMonths();
}
render() {
if (this.props.data === undefined) {
return (
<button onClick={this.login}>Login</button>
)
} else if (this.props.data !== undefined) {
return (
<main className="main-container">
<Nav user="user"/>
<Switch>
<Route exact path='/' component={CurrentMonth}/>
<Route path='/aktualny' component={CurrentMonth}/>
<Route path='/nowy' component={AddNewMonth}/>
<Route path='/archiwum' component={Archive}/>
<Route path='/ustawienia' component={Settings}/>
</Switch>
</main>
);
}
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ fetchAllMonths }, dispatch);
}
function mapStateToProps({ data }) {
return { data };
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App))
主要操作,fetchAllMonths:
// import firebase from 'firebase';
// Firebase Config
// import axios from 'axios';
export const FETCH_ALL_MONTHS = 'FETCH_ALL_MONTHS';
export function fetchAllMonths() {
/*const database = firebase.database();
const data = database.ref('/users/grhu').on('value', function(snapshot) {
return snapshot.val();
});
console.log(data) */
const data = fetch('https://my-finances-app-ef6dc.firebaseio.com/users/grhu.json')
.then(async (response) => response.json())
.then(data => {
console.log(data);
return data;
}
)
console.log(data);
return {
type: FETCH_ALL_MONTHS,
payload: data
};
};
Reducers index.js:
import { combineReducers } from "redux";
import data from "./reducer_load_from_db";
const rootReducer = combineReducers({
data: data
});
export default rootReducer;
最后我的减速机:
import { FETCH_ALL_MONTHS } from "../actions/index";
export default function(state = [], action) {
switch (action.type) {
case FETCH_ALL_MONTHS:
return [action.payload.data, ...state];
default:
return state;
}
return state;
}
所以我确信fetch工作正常,因为console.log(data)给了我一个有效的JSON文件,但第二个带有传递const的console.log(数据)给了我一个承诺,然后我发送给你有效载荷到Reducer。 CreateStore似乎也可以工作,因为在React dev控制台中我可以看到App容器中的“数据”道具。我使用redux-promise来解析有效负载中的Promise并将JSON返回给商店,但数据仍未定义。还尝试了redux-promise-middleware,但再次,没有运气。
我错过了什么?我已经看了几个小时的代码,我无法理解它有什么问题。
我会感谢所有答案,但我真的想了解这个问题,而不仅仅是复制粘贴解决方案。
提前致谢!
答案 0 :(得分:-1)
初步回答
根据我在fetchAllMonths()
动作创建者中的内容,您正在为其返回的名为payload
等于的操作设置一个属性,该属性是从您的API调用。
return {
type: FETCH_ALL_MONTHS,
payload: data
};
如果您在减速机中记录了action.payload
,那么......
switch (action.type) {
case FETCH_ALL_MONTHS:
console.log(action.payload)
return [action.payload.data, ...state];
default:
return state;
}
我相信您会看到API调用返回的数据。
那么在你的reducer中你会期望action.payload
作为FETCH_ALL_MONTHS
动作的属性。而你想要使用点差运算符...action.payload
。
另外,为了使您的逻辑更容易阅读,为什么不尝试使用异步操作来获取数据,然后调度一个接受API调用返回的数据的操作?
希望有所帮助!
更新了答案
当我考虑到这一点并阅读您对我的回答的回复时,我认为您可能需要使用异步操作来确保您的数据已成功获取。我使用异步操作创建了一个非常简单的CodePen示例。
https://codepen.io/joehdodd/pen/rJRbZG?editors=0010
让我知道这是否有帮助,如果你让它以这种方式运作。