代码之家  ›  专栏  ›  技术社区  ›  Salman

react redux productlist添加/删除w/bindactioncreator

  •  2
  • Salman  · 技术社区  · 6 年前

    我正试图在React中创建一个产品列表,我可以在其中添加和删除产品。

    我开始研究如何使用 redux 框架/平台和本地响应

    我已经有功能了 productList 集装箱, product 组件和 cartList , cartProduct 组件。

    我的问题是:

    产品:我只能添加产品,不能删除

    购物车:反之亦然+购物车不会更新购物车项目的状态。

    我已经添加了BindActionCreator,但还不知道如何将其应用于我的产品列表。

    我期望会发生什么? 我尝试在同一容器/组件中添加和删除React Store中的产品。

    我该怎么做?我的方法是正确的还是完全错误的?

    A事先谢谢你。

    产品操作创建者

    export const ADD_TO_CART = 'ADD_TO_CART'
    export const REMOVE_FROM_CART = 'REMOVE_FROM_CART'
    
    export function addItemToCart(row) {
        return {
            type:'ADD_TO_CART', 
            payload: row, qty
        }
      }
    
      export function removeTodo(row) {
        return {
            type:'REMOVE_FROM_CART' , 
            payload: row, qty
        }
      }
    

    产品列表(简化)

         import React from 'react';
         import { Component } from 'react';
          import { 
            View,  
            StyleSheet, 
            Text
         } from 'react-native';
         import Products from '../components/Products';
         import { bindActionCreators} from 'redux';
         import { connect } from 'react-redux';
    
         import * as ProductActionCreators from '../actions/ProductActionCreators'
    
         export  class ProductList extends React.Component {
            static navigationOptions = {
                header: null,
            };
            constructor(props) {
                super(props);
                const { rows } = this.props.navigation.state.params;
                const arrays = Object.values( {rows});
                this.state = {
                    arrays,
                    filteredProducts: arrays,
                };
                const { dispatch } = props
                this.boundActionCreators = bindActionCreators(ProductActionCreators, dispatch)
                console.log(this.boundActionCreators)
            }
    
    
    
              render() {
                return (
                    <View style={styles.container} >
                    <Text style={styles.title} >
                        {this.state.arrays[0].name}
                    </Text>
                        <Products products={this.state.arrays[0].data} onPress=
    //Trying to change this to multiple actions
    {this.props.addItemToCart}/>    
                    </View>
                )
              }
            }
    
        const qty = 0;
    
        const mapDispatchToProps = (dispatch) =>{
            //need to add BindActionCreator
            return{
                addItemToCart:(row) => dispatch({
                    type:'ADD_TO_CART', payload: row, qty
    
                }),
                removeItem:(product) => dispatch ({
                    type:'REMOVE_FROM_CART' , payload: product, qty
                })  
            }
    
        }
    
        export default connect(null, mapDispatchToProps) (ProductList);
    

    产品(简化)

    import React, { Component } from "react";
    import {
        View,
        Text,
        TouchableOpacity,
        TextInput,
        FlatList,
    } from "react-native";
    import Icon from "react-native-vector-icons/Ionicons";
    
    class Products extends Component {
        constructor(props) {
            super(props);
            const { products } = this.props;
            this.state = {
                products, 
                filteredProducts: products,
            };
        }
        renderProducts = (products) => {
                return (
                    <View key={products.index}>
                        <View> 
                            <Icon name={products.item.icon} color="#DD016B" size={25} />
                        </View>
                        <View>
                            <Text style={styles.name}>
                                {products.item.name}
                            </Text>
                            <Text>
                            € {products.item.price}
                            </Text>
                        </View>
                        <View style={styles.buttonContainer}>
                            <TouchableOpacity onPress={() => this.props.onPress(products.item)} > 
                                <Icon name="ios-add" color="white" size={25} />
                            </TouchableOpacity>
    
                            <TouchableOpacity onPress={() => this.props.onPress(products.item)} > 
                                <Icon name="ios-remove" color="white" size={25} />
                            </TouchableOpacity>
    
                        </View>
                    </View>
                )
        }
    
        render() {
            return (
                <View>
                    <FlatList
                    style={styles.listContainer}
                    data={this.state.filteredProducts}
                    renderItem={this.renderProducts}
                    keyExtractor={(item, index) => index.toString()}
                    />
                </View>
            );
        }
    }
    
    export default Products;
    

    异径管/推车

    const cartItems = (state = [], action) => {
        switch (action.type)
        {
            case 'ADD_TO_CART':
                if (state.some(cartItem => cartItem.id === action.payload.id)) {
                    // increase qty if item already exists in cart
                    return state.map(cartItem => (
                        cartItem.id === action.payload.id ? { ...cartItem, qty: cartItem.qty + 1 } : cartItem
    
                        ));            
                }
                return [...state, { ...action.payload, qty: 1 }]; 
                // else add the new item to cart            
            case 'REMOVE_FROM_CART':
                return state
                    .map(cartItem => (cartItem.id === action.payload.id ? { ...cartItem, qty: cartItem.qty - 1 } : cartItem))
                    .filter(cartItem => cartItem.qty > 0);
        }
        return state
    } 
    export default cartItems 
    

    存储/索引

    import {createStore} from 'redux';
    import cartItems from '../reducers/carItems';
    
    export default store = createStore(cartItems)
    

    应用程序结构(简化)

    Main folder
            ↳
              Containers(folder)
                ↳
                 ProductsList.js
                 CartList.js
    
              Components(folder)
                ↳
                 Product.js
                 cartProduct.js
    
              Reducers(folder)
                ↳
                 carItems.js
    
              Actions(folder)
                ↳ 
                 ProductActionCreators.js
    
              Navigation(folder)
                ↳
                 AppNavigator,js
                 MainTabNavigator.js
    
              Assets(folder for images etc.)
              Store(folder)
                ↳
                 index.js
              App.JS
              Data.JS (using static JSON file for this development phase)
    
    3 回复  |  直到 6 年前
        1
  •  3
  •   Shubham Khatri    6 年前

    你有两种不同的行为, addItemToCart , removeItem 在mapdispatchtoprops中定义。既然指定了一个mapdispatchtoprops参数进行连接,那么调度方法就不能作为连接组件的属性使用,而是只能使用mapdispatchtoprops返回的方法。

    第二, 你不需要使用 bindActionCreators 当然不在组件中。 MapDispatchToProps 可以只是一个对象,Connect将在内部使用Dispatch。

    第三 ,您需要将添加和删除操作都传递给子组件。

    第四 您可以将多个操作作为道具简单地传递给产品组件

    你的代码应该是

    ProductActionCreators.js版本

    export const ADD_TO_CART = 'ADD_TO_CART'
    export const REMOVE_FROM_CART = 'REMOVE_FROM_CART'
    
    export function addItemToCart(row) {
        return {
            type:'ADD_TO_CART', 
            payload: row
        }
      }
    
      export function removeItem(item) {
        return {
            type:'REMOVE_FROM_CART' , 
            payload: item
        }
      }
    

    产品目录

      import React from 'react';
      import { Component } from 'react';
      import { 
        View,  
        StyleSheet, 
        Text
     } from 'react-native';
     import Products from '../components/Products';
     import { connect } from 'react-redux';
    
     import { addItemToCart, removeItem } from '../actions/ProductActionCreators';
    
     export  class ProductList extends React.Component {
        static navigationOptions = {
            header: null,
        };
        constructor(props) {
            super(props);
            const { rows } = this.props.navigation.state.params;
            const arrays = Object.values( {rows});
            this.state = {
                arrays,
                filteredProducts: arrays,
            };
        }
    
    
    
          render() {
            return (
                <View style={styles.container} >
                <Text style={styles.title} >
                    {this.state.arrays[0].name}
                </Text>
                    <Products products={this.state.arrays[0].data} addItemToCart={this.props.addItemToCart} removeItem={this.props.removeItem}/>    
                </View>
            )
          }
        }
    
    
    const mapDispatchToProps =  {
         addItemToCart,
         removeItem
    }
    
    export default connect(null, mapDispatchToProps) (ProductList);
    

    产品

    import React, { Component } from "react";
    import {
        View,
        Text,
        TouchableOpacity,
        TextInput,
        FlatList,
    } from "react-native";
    import Icon from "react-native-vector-icons/Ionicons";
    
    class Products extends Component {
        constructor(props) {
            super(props);
            const { products } = this.props;
            this.state = {
                products, 
                filteredProducts: products,
            };
        }
        renderProducts = (products) => {
                return (
                    <View key={products.index}>
                        <View> 
                            <Icon name={products.item.icon} color="#DD016B" size={25} />
                        </View>
                        <View>
                            <Text style={styles.name}>
                                {products.item.name}
                            </Text>
                            <Text>
                            € {products.item.price}
                            </Text>
                        </View>
                        <View style={styles.buttonContainer}>
                            <TouchableOpacity onPress={() => this.props.addItemToCart(products.item)} > 
                                <Icon name="ios-add" color="white" size={25} />
                            </TouchableOpacity>
    
                            <TouchableOpacity onPress={() => this.props.removeItem(products.item)} > 
                                <Icon name="ios-remove" color="white" size={25} />
                            </TouchableOpacity>
    
                        </View>
                    </View>
                )
        }
    
        render() {
            return (
                <View>
                    <FlatList
                    style={styles.listContainer}
                    data={this.state.filteredProducts}
                    renderItem={this.renderProducts}
                    keyExtractor={(item, index) => index.toString()}
                    />
                </View>
            );
        }
    }
    
    export default Products;
    
        2
  •  1
  •   vijayst    6 年前

    代码在大多数情况下看起来都不错。

    productList中的react redux connect部分看起来很不起眼。数量始终为0。应该是1。

    此外,还应提供mapstatetoprops以从购物车中获取产品。

        3
  •  1
  •   tombraider    6 年前

    在你 ProductList 我会像这样处理动作绑定:

    const mapDispatchToProps = (dispatch) =>{
        return bindActionCreators({
            addItemToCart: (row, qty) => dispatch({
                type:'ADD_TO_CART', payload: {row, qty}
            }),
            removeItem: (product, qty) => dispatch({
                type:'REMOVE_FROM_CART' , payload: {product, qty}
            })  
        })
    }
    
    export default connect(null, mapDispatchToProps)(ProductList);
    

    从组件的构造函数中删除操作绑定,因为这是不必要的。

    您可能希望将代码拆分为 Container / Component /hoc方法,我发现它使代码更容易阅读。因为您在单独的文件中定义了您的操作,所以我也会导入这些操作,而不是重新声明它们。

    如果你遵循这个建议,你会得到以下结果:

    集装箱船

    import { bindActionCreators } from 'redux';
    import ProductList from './product-list';
    
    // Actions
    import { addItemToCart, removeItem } from './actions';
    
    function mapStateToProps(state) {
        return {}
    }
    
    function mapDispatchToProps(dispatch) {
        return bindActionCreators({
            addItemToCart,
            removeItem,
        })
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(ProductList);
    

    产品列表

    import React from 'react';
    import { View, Text } from 'react-native';
    import Products from '../components/Products';
    
    export  class ProductList extends React.Component {
        static navigationOptions = {
            header: null,
        };
        constructor(props) {
            super(props);
            const { rows } = this.props.navigation.state.params;
            const arrays = Object.values( {rows});
            this.state = {
                arrays,
                filteredProducts: arrays,
            };
    
            this.handleProductPress = this.handleProductPress.bind(this);
        }
    
        handleProductPress(e) {
            e.preventDefault();
            // This is pseudo code...
            this.props.addItemToCart(e.target.value, 1);
            return;
        } 
    
        render() {
            return (
                <View style={styles.container} >
                    <Text style={styles.title} >
                        {this.state.arrays[0].name}
                    </Text>
                    <Products products={this.state.arrays[0].data} onPress={this.handleProductPress} />
               </View>
            ) 
        }
    }
    
    export default ProductList;
    

    玩一玩,看看你怎么样。

    推荐文章