【问题标题】:Redux action working only with bindActionCreatorsRedux 操作仅适用于 bindActionCreators
【发布时间】:2020-01-26 22:45:08
【问题描述】:

我有一个简单的 React & Redux 应用程序,但我遇到了奇怪的问题。 这里是我项目的主要文件:

Home.js 文件:

import React, { Component } from "react";
import { bindActionCreators } from "redux";
import * as productActions from "../../actions/product";
import { connect } from "react-redux";

class Home extends Component {
    componentWillMount() {
        this.props.actions.getProducts();
    }

    render() {
        const { products, actions } = this.props;
        const cart = products.filter(product => product.addToCart);

        return (
            <div className="home mt-5">
                <div className="row">
                    <div className="col-12">
                        <h2 className="mb-3">Products</h2>
                    </div>
                </div>
                <div className="row mt-3">
                    {products.map(product => (
                        <div key={product.id} className="col-sm-6 col-md-3">
                            <div
                                className="view_details"
                                onClick={() => actions.addToCart(product)}
                            >
                                {product.name}{" "}
                                <u>{product.addToCart ? "Remove" : "Add to Cart"}</u>
                            </div>
                        </div>
                    ))}
                </div>
                <div className="row mt-4">
                    <div className="col-12">
                        <h2 className="mb-3">Cart:</h2>
                        {cart.map(product => (
                            <div key={product.id}>{product.name}</div>
                        ))}
                    </div>
                </div>
            </div>
        );
    }
}

export default connect(
    state => ({
        products: state.product.products
    }),
    dispatch => ({
        actions: bindActionCreators(productActions, dispatch)
    })
)(Home);

actions/product.js 文件:

import { FETCH_PRODUCTS_DATA, ADD_TO_CART } from "../types/products";

export const getProducts = () => dispatch =>
    fetch(`data.json`)
        .then(response => response.json())
        .then(response => {
            dispatch({
                type: FETCH_PRODUCTS_DATA,
                payload: response.products
            });
        });

export const addToCart = product => ({
    type: ADD_TO_CART,
    product
});

reducers/productReducer.js 文件:

import { FETCH_PRODUCTS_DATA, ADD_TO_CART } from "../types/products";

const initialState = {
    products: []
};

export default function(state = initialState, action) {
    switch (action.type) {
        case FETCH_PRODUCTS_DATA:
            return {
                ...state,
                products: action.payload.map(product => ({
                    ...product,
                    addToCart: false
                }))
            };
        case ADD_TO_CART:
            return {
                ...state,
                products: state.products.map(product =>
                    product.id === action.product.id
                        ? { ...product, addToCart: !product.addToCart }
                        : product
                )
            };
        default:
            return state;
    }
}

这里还有更多不需要与您分享的文件。 上面的代码一切都按预期工作,问题是当我不使用 bindActionCreators 方法时。 使用以下 Home.js 文件(带有 mapStateToProps 和 mapDispatchToProps),只有 getProducts 操作运行良好,但 addToCart 操作给我以下错误:“无法读取未定义的属性 'id'”:reducers/productReducer.js: 20

带有 mapStateToProps 和 mapDispatchToProps 的 Home.js 文件:

import React, { Component } from "react";
import { getProducts, addToCart } from "../../actions/product";
import { connect } from "react-redux";

class Home extends Component {
    componentWillMount() {
        this.props.actions.getProducts();
    }

    render() {
        const { products, actions } = this.props;
        const cart = products.filter(product => product.addToCart);

        return (
            <div className="home mt-5">
                <div className="row">
                    <div className="col-12">
                        <h2 className="mb-3">Products</h2>
                    </div>
                </div>
                <div className="row mt-3">
                    {products.map(product => (
                        <div key={product.id} className="col-sm-6 col-md-3">
                            <div
                                className="view_details"
                                onClick={() => actions.addToCart(product)}
                            >
                                {product.name}{" "}
                                <u>{product.addToCart ? "Remove" : "Add to Cart"}</u>
                            </div>
                        </div>
                    ))}
                </div>
                <div className="row mt-4">
                    <div className="col-12">
                        <h2 className="mb-3">Cart:</h2>
                        {cart.map(product => (
                            <div key={product.id}>{product.name}</div>
                        ))}
                    </div>
                </div>
            </div>
        );
    }
}


const mapStateToProps = state => {
    return {
        products: state.product.products
    };
};
const mapDispatchToProps = dispatch => {
    return {
        actions: {
            getProducts: () => dispatch(getProducts()),
            addToCart: () => dispatch(addToCart())
        }
    };
};
export default connect(mapStateToProps, mapDispatchToProps)(Home);

谁能告诉我为什么?

谢谢!

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    这是你的错误

    const mapDispatchToProps = dispatch => {
        return {
            actions: {
                getProducts: () => dispatch(getProducts()),
                addToCart: () => dispatch(addToCart())
            }
        };
    };
    

    addToCart 接受 1 个参数,product。但是当你不使用bindActionCreators 时,addToCart 没有参数。您正在发送 addToCart{} 没有任何参数。 products === undefined 你有错误。

    要解决,请将参数添加到addToCart

    const mapDispatchToProps = dispatch => {
        return {
            actions: {
                getProducts: () => dispatch(getProducts()),
                addToCart: (product) => dispatch(addToCart(product))
            }
        };
    };
    

    【讨论】:

    • 谢谢,它有效!请再问一个问题,在操作文件中有两个功能。 getProducts函数里面有dispatch函数的用法,addToCart里面没有,为什么?每个动作都应该使用调度功能?当我需要在动作中使用调度功能时?谢谢@Fyodor
    • getProducts 是一个async action creator。这是一个返回另一个函数的函数。这个返回的函数(接受 dispatch 作为参数)将被 thunk 中间件调用。 addToCart 只是一个返回动作(普通对象)的函数。它是synchronous action creator,不需要。 dispatch 请不要忘记接受答案 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 2016-02-27
    • 1970-01-01
    • 2018-12-23
    • 2017-06-04
    • 2016-11-29
    • 1970-01-01
    相关资源
    最近更新 更多