首页 文章

Redux reducer不会更新store / redux-promise无法解析

提问于
浏览
0

所以我最近开始学习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(data)给了我一个promise,然后我作为一个有效负载发送给一个减速器 . CreateStore似乎也可以工作,因为在React dev控制台中我可以看到App容器中的“数据”道具 . 我使用redux-promise来解析有效负载中的Promise并将JSON返回给商店,但数据仍未定义 . 还尝试了redux-promise-middleware,但再次,没有运气 .

我错过了什么?我已经看了几个小时的代码,我无法理解它有什么问题 .

我会很感激所有的答案,但我真的想了解这个问题,而不仅仅是复制粘贴解决方案 .

提前致谢!

1 回答

  • -1

    Initial Answer

    根据我在 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调用返回的数据 .

    那么在你的减速器中你会期望 action.payload 作为 FETCH_ALL_MONTHS 动作的属性 . 而你想要使用扩展运算符 ...action.payload .

    另外,为了使您的逻辑更容易阅读,为什么不尝试使用异步操作来获取数据,然后调度一个接受API调用返回的数据的操作?

    希望有所帮助!

    Updated Answer

    当我想到这一点并阅读您对我的回答的回复时,我认为您可能需要使用异步操作来确保您的数据已成功获取 . 我使用异步操作创建了一个非常简单的CodePen示例 .

    https://codepen.io/joehdodd/pen/rJRbZG?editors=0010

    让我知道,如果这有帮助,如果你让它以这种方式工作 .

相关问题