简体   繁体   English

在React中调度Redux操作

[英]Dispatch Redux action in React

I'm trying to fetch test API using FetchAPI and Redux. 我正在尝试使用FetchAPI和Redux获取测试API。

The problem is with dispatch redux action. 问题出在调度还原动作上。

Here's my code: 这是我的代码:

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) product.js(操作)

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) product.js(减速器)

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 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;

The line console.log("fetchProductsWithRedux-2"); 行console.log(“ fetchProductsWithRedux-2”); in ProductList.js has never been reached. 尚未到达ProductList.js中。

What's wrong? 怎么了? Any ideas? 有任何想法吗? Thanks in advance. 提前致谢。

seem you missed import thunk from 'redux-thunk'. 看来您错过了'redux-thunk'的进口thunk。 You can't return a function in redux action if you dont use any middleware like 'redux-thunk' 如果不使用“ redux-thunk”之类的中间件,则无法在redux操作中返回函数

There are a few issues with your code. 您的代码存在一些问题。

Firstly, fetchProductsWithRedux is an action, so you would need to dispatch it rather than calling it directly. 首先,fetchProductsWithRedux是一个动作,因此您需要分派它而不是直接调用它。 As Bjoern mentioned, the way you are calling it, the function call just returns a function, which is never called. 正如Bjoern所述,在调用它的方式中,函数调用只会返回一个函数,而该函数永远不会被调用。

Now, you cannot dispatch it in the current scenario, as it returns a function, rather than object. 现在,您无法在当前方案中调度它,因为它返回的是函数而不是对象。 To fix that, you will have to use redux-thunk, which will allow it to dispatch a function. 要解决此问题,您将必须使用redux-thunk,这将允许它分派一个函数。

You can add it to mapDispatchToProps, as you did for getProducts, but there is a shorthand for that. 您可以像对getProducts一样将其添加到mapDispatchToProps中,但是有一个简写形式。 In your mapDispatchToProps, you can do the following:- 在您的mapDispatchToProps中,您可以执行以下操作:

 const mapDispatchToProps = { fetchProductsWithRedux, getProducts }

You will notice that it is just returning an object with 2 functions. 您会注意到,它只是返回带有2个函数的对象。

From the documentation: 从文档中:

If an object is passed, each function inside it is assumed to be a Redux action creator. 如果传递了一个对象,则假定其中的每个函数都是Redux操作创建者。 An object with the same function names, but with every action creator wrapped into a dispatch call so they may be invoked directly, will be merged into the component's props. 一个具有相同功能名称的对象,但每个动作创建者都包装在一个调度调用中,以便可以直接调用它们,这些对象将合并到组件的props中。

So, it will do exactly what you did earlier with bindActionCreators, but it looks more elegant. 因此,它将与您之前对bindActionCreators所做的完全一样,但是看起来更加优雅。 Now, instead of onClick={this.props.action.getProducts} , you can do onClick={this.props.getProducts} . 现在,而不是onClick={this.props.action.getProducts} ,你可以做onClick={this.props.getProducts} Notice the missing action. 请注意缺少的action.

Also, your import will change to 另外,您的导入将更改为

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

Now, to fix your issue, in componentDidMount, rather than calling the function directly, you will have to do:- 现在,要解决问题,请在componentDidMount中,而不是直接调用该函数,您必须执行以下操作:

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

Hopefully, this will help. 希望这会有所帮助。

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

This returns a function function(dispatch){...} , which is not called in 这将返回一个函数function(dispatch){...} ,该函数未在中调用

componentDidMount() {
    fetchProductsWithRedux();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM