Redux Thunk用于简单的异步请求

时间:2018-08-20 16:08:02

标签: javascript api asynchronous redux redux-thunk

我正在构建一个简单的应用程序,以从API URL检索一些食谱。 我正在阅读Thunk的文档以实现它,但我不明白如何设置异步获取请求。 奇怪的是,如果我在console.log中将传递到减速器中的动作肯定检索到正确的对象(切碎鸡肉的食谱列表)。 当我将动作传递给reducer时,它将引发错误:

“未处理的拒绝(错误):给定操作“ FETCH_RECIPES”,减速器“ recipes”返回未定义。要忽略某个动作,必须显式返回先前的状态。如果希望此减速器不保留任何值,则可以返回null而不是未定义。”

我的动作创建者是否有任何错误? API调用正确完成了吗?

商店

import React from 'react';
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware } from 'redux'
import SearchBar from './components/App';
import thunk from 'redux-thunk';
import 'bootstrap/dist/css/bootstrap.css';



import rootReducer from './reducers';

const store = createStore(rootReducer, applyMiddleware(thunk));

render(
    <Provider store={store}>
      <SearchBar />
    </Provider>,
    document.getElementById('root')
  )

组件

import React, { Component } from 'react';
import { connect } from 'react-redux';
import './App.css';
import { Button } from 'reactstrap';
import { Form } from 'reactstrap';
import { bindActionCreators } from 'redux';
import  {fetchRecipe } from '../actions';

class SearchBar extends Component {
  constructor(props) {
    super(props)


    this.state = { term: ''};
    this.typeRecipe = this.typeRecipe.bind(this)
    this.onFormSubmit = this.onFormSubmit.bind(this);  
  }

  onFormSubmit(e) {
    e.preventDefault()

    this.props.fetchRecipe(this.state.term)
  }


  typeRecipe(e) {
    this.setState({term: e.target.value});

  }

  render() {
    return (
      <div className="SearchBar">
         <Form onSubmit={this.onFormSubmit}>
            <input type='text'
            value={this.state.term}
            placeholder='ciao'
            onChange={this.typeRecipe}
             />
             <br/>
            <Button id='ciao' className='btn-success'>Submit</Button>
         </Form>
      </div>
    );
  }
}


function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchRecipe }, dispatch);
}


export default connect(null, mapDispatchToProps)(SearchBar);

动作创建者

import axios from 'axios';

export const FETCH_RECIPES = 'FETCH_RECIPES';


const API_KEY = 'xxx';//not the real one.

export function fetchRecipe() {
   const request = axios.get(`http://food2fork.com/api/search?key=${API_KEY}&q=shredded%20chicken`);

   return (dispatch) => {
    request.then(({data}) =>{
        dispatch({ type: FETCH_RECIPES, payload: data})
    })
}


}

减速器

import { FETCH_RECIPES } from '../actions';

export default function (state = {}, action) {
    switch(action.type) {
        case FETCH_RECIPES:
            const newState = action.payload.data;                    
            return newState;
        default:
            return state
 }
}

combineReducer(索引)

import recipeReducer from '../reducers/recipes_reducer';
import { combineReducers } from 'redux';

const rootReducer = combineReducers({
    recipes: recipeReducer 
});

export default rootReducer;

1 个答案:

答案 0 :(得分:1)

Mistake在减速器的return语句中。

export default function (state = {}, action) {
    switch(action.type) {
        case FETCH_RECIPES:
            const newState = {...state, data : action.payload.data};                    
            return newState;
        default:
            return state
 }
}

在这里,我们将data键添加到reducer状态,可以在容器中使用它来访问此键:

export default connect((state)=>{
    var mapStateToProps = {};
    if(state.recipes.data) {
        mapStateToProps['recipes'] =  state.recipes.data
    }
    return mapStateToProps;    

 }, mapDispatchToProps)(SearchBar);

和配方数据将以this.props.recipes的形式提供。