在React

时间:2017-06-08 09:56:51

标签: reactjs redux react-redux dispatch

我尝试使用FetchAPI和Redux获取测试API。

问题在于dispatch redux操作。

这是我的代码:

ProductList.js
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as productActions from '../actions/product';
import RaisedButton from 'material-ui/RaisedButton';

function fetchProductsWithRedux() {
    console.log("fetchProductsWithRedux-1");
    return (dispatch) => {
        console.log("fetchProductsWithRedux-2");
        dispatch(this.props.action.fetchProdutcsRequest());
        return fetchProdutcs().then(([response, json]) => {
            if (response.status === 200) {
                console.log("success");
                dispatch(this.props.action.fetchProductsSucesss(json))
            }
            else {
                console.log("error");
                dispatch(this.props.action.fetchProductsError())
            }
        })
    }
}

function fetchProdutcs() {
    const URL = "https://jsonplaceholder.typicode.com/posts";
    return fetch(URL, { method: 'GET' })
        .then(response => Promise.all([response, response.json()]));
}


class ProductList extends Component {
    constructor(props) {
        super(props);
        this.state = {
            productList: [
                'product 1',
                'product 2',
                'product 3'
            ]
        }
    }
    componentDidMount() {
        fetchProductsWithRedux();
    }
    render() {
        return (
            <div className="ProductList">
                <h2>Products</h2>
                <ul>
                    {
                        this.props.posts &&
                        this.props.posts.map((post) => {
                            return (
                                <li>{post.title}</li>
                            )
                        })
                    }
                </ul>

                <ol>
                    <RaisedButton label="Get Products Action" onClick={this.props.action.getProducts} />
                </ol>
            </div>
        );
    }
}

function mapStateToProps(state, props) {
    return {
        product: state.product,
        posts: state.posts
    };
}
function mapDispatchToProps(dispatch) {
    return {
        action: bindActionCreators(productActions, dispatch)
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(ProductList);

product.js(actions)

export function fetchProductsRequest() {
  console.log('fetchProductsRequest');
  return {
    type: 'FETCH_PRODUCTS_REQUEST'
  }
}

export function fetchProductsSuccess(payload) {
  console.log('fetchProductsSuccess');
  return {
    type: 'FETCH_PRODUCTS_SUCCESS'
  }
}

export function fetchProductsError() {
  console.log('fetchProductsError');
  return {
    type: 'FETCH_PRODUCTS_ERROR'
  }
}

product.js(reducer)

export default(state = [], payload) => {
    switch (payload.type) {
        case 'FETCH_PRODUCTS_REQUEST':
            console.log('FETCH_PRODUCTS_REQUEST action');
            return state;
        case 'FETCH_PRODUCTS_SUCCESS':
            console.log('FETCH_PRODUCTS_SUCCES action');
            return {...state, posts: payload.payload}
        default:
            return state;
    }
};

store.js

import { createStore } from 'redux';
import rootReducer from './reducers';

export default(initialState) => {
    return createStore(rootReducer, initialState);
}

Product.js (pages, component)
import React, { Component } from 'react';
import ProductList from '../../components/ProductList';
import RaisedButton from 'material-ui/RaisedButton';
//import './Product.css';

class Product extends Component {
    render() {
        return (
            <div className="Product">
                <h1>ProductList Page</h1>
                <RaisedButton label="Default" />
                <ProductList />
            </div>
        );
    }
}
export default Product;

行console.log(&#34; fetchProductsWithRedux-2&#34;);从未到达过ProductList.js。

出了什么问题?有任何想法吗?提前谢谢。

3 个答案:

答案 0 :(得分:2)

似乎你错过了来自&#39; redux-thunk&#39;的输入。如果您不使用任何类似于&#39; redux-thunk&#39;

的中间件,则无法在redux操作中返回函数

答案 1 :(得分:1)

您的代码存在一些问题。

首先,fetchProductsWithRedux是一个动作,所以你需要调度它而不是直接调用它。正如Bjoern所提到的,你调用它的方式,函数调用只返回一个永远不会被调用的函数。

现在,您无法在当前场景中调度它,因为它返回一个函数,而不是对象。要解决这个问题,你必须使用redux-thunk,这将允许它调度一个函数。

您可以将其添加到mapDispatchToProps,就像您为getProducts所做的那样,但有一个简写。在mapDispatchToProps中,您可以执行以下操作: -

 const mapDispatchToProps = { fetchProductsWithRedux, getProducts }

您会注意到它只返回一个包含2个函数的对象。

来自文档:

  

如果传递了一个对象,则假定其中的每个函数都是Redux动作创建者。具有相同函数名称的对象,但每个动作创建者都包含在一个调度调用中,因此可以直接调用它们,它们将合并到组件的道具中。

因此,它将完全与您之前使用bindActionCreators所做的一样,但它看起来更优雅。现在,您可以onClick={this.props.action.getProducts}而不是onClick={this.props.getProducts}。请注意丢失的action.

此外,您的导入将更改为

import { getProducts } from '../actions/product';

现在,为了解决您的问题,在componentDidMount中,而不是直接调用该函数,您将不得不这样做: -

componentDidMount() {
   this.props.fetchProductsWithRedux();
}

希望这会有所帮助。

答案 2 :(得分:0)

function fetchProductsWithRedux() {
console.log("fetchProductsWithRedux-1");
return (dispatch) => {
    console.log("fetchProductsWithRedux-2");
    ...
    }

这将返回一个函数function(dispatch){...},该函数未在

中调用
componentDidMount() {
    fetchProductsWithRedux();
}