【问题标题】:Redux Asynchronous Request Issue (Thunk Middleware)Redux 异步请求问题(Thunk 中间件)
【发布时间】:2016-12-08 04:54:18
【问题描述】:

所以我可能会过度思考这个问题,但我似乎无法让我的组件异步工作。

本质上,我使用 thunk 来调度一个动作,该动作将从本地服务器检索 JSON,一旦接收到,将其传递给 reducer 并更新状态,然后渲染组件。

相反,组件接收应用程序的初始状态为{} 空对象,因此当我使用map 呈现组件时会出错。

这是我所拥有的:

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import thunk from 'redux-thunk';
import promise from 'redux-promise';

import App from './components/app';
import VotesContainer from './containers/votes-container';
import NewPoll from './containers/newpoll';
import VoteTemplate from './components/vote-template';
import Login from './components/auth/login';
import Signup from './components/auth/signup';
import reducers from './reducers/';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(reducers, composeEnhancers(applyMiddleware(thunk)))

ReactDOM.render(
  <Provider store={store}>
    <Router history={browserHistory}>
      <Route path="/" component={App}>
        <IndexRoute component={VoteTemplate} />
        <Route path="allposts" component={VotesContainer} />
        <Route path="login" component={Login} />
        <Route path="signup" component={Signup} />
        <Route path="newpoll" component={NewPoll} />
      </Route>
    </Router>
  </Provider>
  , document.querySelector('#project'));

actions/index.js

import axios from 'axios';
const ROOT_URL = 'http://localhost:1234';
import { browserHistory } from 'react-router';
import { FETCH_VOTES, CAST_VOTE } from './types';

export function fetchVotes(){
  return function(dispatch){
    axios.get(`${ROOT_URL}/newpost`)
      .then(response => {
        console.log('Dispatch!!')
        dispatch({
          type: FETCH_VOTES,
          payload: response.data
        })
      })
  }
}

容器

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions'

class VotesContainer extends Component {
  componentDidMount(){
    this.props.fetchVotes()
  }
  renderCards(){
    return(
      <div className="col s12 m6 l4">
        <div className="card blue-grey darken-1">
          <div className="card-content white-text">
            <span className="card-title">Vote App Title #1</span>
            <p className="description">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
          </div>
          <div className="card-action">
            <a href="#">Results</a>
            <a href="#">Date Created</a>
          </div>
        </div>
      </div>
    )
  }
  render(){
    console.log(this.props.voteData)
    return(
      <main className="votes-container container">
        <div className="row">
          {this.props.voteData.map(this.props.voteData.vote)} <<======= gives error since it is null first before dispatch
        </div>
      </main>
    )
  }
}

function mapStateToProps(state){
  return {voteData: state.voteData};
}

export default connect(mapStateToProps, actions)(VotesContainer)

【问题讨论】:

  • 你不能在一个对象上使用 map,你想用它作为对象键吗?
  • 抱歉打错了,应该是this.props.voteData.vote
  • 可以防阵列。做(this.props.voteData.vote || []).map(this.renderCards) 会做你想做的事。您将从一个空对象的初始状态开始,然后当您分派它时,它将被填充,除非您想从服务器的另一个初始状态开始?
  • 太棒了,看起来它完成了这项工作!但是,我仍然很好奇为什么我的 redux-thunk 设置无法正常工作
  • 这里有更多信息:github.com/reactjs/redux/blob/master/docs/advanced/…。基本上,您需要在调用将修改状态为 FETHCING 的 API 之前分派一个操作,然后一旦您有响应,您就将其更改为 DONE。随附的链接很好地说明了这一点。

标签: reactjs asynchronous react-redux redux-thunk


【解决方案1】:

您应该使用您对组件的期望来设置商店的一些初始状态。
如果您不这样做,那么您不应该期望所有数据都在第一个 render 中。数据只有在获取之后才会来,在那之前你还不如在组件中添加一些安全检查。

【讨论】:

  • 啊,我明白了。我会认为当调用componentDidMount 并且它正在异步获取时,它不会在获取数据之前呈现组件。是的,只需添加安全检查,它就可以完美运行
  • @Alejandro:不,在等待数据时,渲染将被调用,因为等待数据将是一个异步过程。一旦接收到数据 -> 状态更新 -> 再次调用渲染
猜你喜欢
  • 2019-01-26
  • 2021-06-15
  • 2017-07-28
  • 2016-04-24
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
相关资源
最近更新 更多