Отправка действия Redux в React

Я пытаюсь получить тестовый API, используя FetchAPI и 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 (действия)

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 (редуктор)

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("fetchProductsWithRedux-2"); в ProductList.js никогда не был достигнут.

Что случилось? Любые идеи? Заранее спасибо.


person mskuratowski    schedule 08.06.2017    source источник
comment
Вы должны использовать промежуточное ПО redux-thunk. Примените его в магазине.   -  person Gnanesh    schedule 08.06.2017


Ответы (3)


кажется, вы пропустили преобразователь импорта из «redux-thunk». Вы не можете вернуть функцию в действии избыточности, если вы не используете какое-либо промежуточное программное обеспечение, такое как 'redux-thunk'

person M.Tae    schedule 08.06.2017

Есть несколько проблем с вашим кодом.

Во-первых, fetchProductsWithRedux — это действие, поэтому вам нужно отправить его, а не вызывать напрямую. Как упомянул Бьорн, то, как вы это называете, вызов функции просто возвращает функцию, которая никогда не вызывается.

Теперь вы не можете отправить его в текущем сценарии, так как он возвращает функцию, а не объект. Чтобы исправить это, вам нужно будет использовать redux-thunk, который позволит отправить функцию.

Вы можете добавить его в mapDispatchToProps, как вы сделали это для getProducts, но для этого есть сокращение. В вашем mapDispatchToProps вы можете сделать следующее:

 const mapDispatchToProps = { fetchProductsWithRedux, getProducts }

Вы заметите, что он просто возвращает объект с двумя функциями.

Из документации:

Если объект передается, предполагается, что каждая функция внутри него является создателем действия Redux. Объект с теми же именами функций, но с каждым создателем действия, обернутым в диспетчерский вызов, чтобы их можно было вызывать напрямую, будет объединен с реквизитами компонента.

Таким образом, он будет делать то же самое, что вы делали ранее с bindActionCreators, но выглядит более элегантно. Теперь вместо onClick={this.props.action.getProducts} можно сделать onClick={this.props.getProducts}. Обратите внимание на отсутствующий action.

Кроме того, ваш импорт изменится на

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

Теперь, чтобы исправить вашу проблему, в componentDidMount вместо прямого вызова функции вам нужно будет сделать: -

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

Надеюсь, это поможет.

person Abhishek Jain    schedule 08.06.2017

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

Это возвращает функцию function(dispatch){...}, которая не вызывается в

componentDidMount() {
    fetchProductsWithRedux();
}
person Björn Böing    schedule 08.06.2017