当前位置: 首页 > 面试题库 >

如何在Redux中调度函数?

谭骏
2023-03-14
问题内容

我在redux存储中有一个Cart数组,其中包含我添加到购物车中的所有项目

像这样

const initialState = {
  cart: [
    {
      product: {
        id: 1,
        name: 'Pizza cheese',
        price: 100,
        image: require('../../assets/food-3.png'),
        description: 'Tempor aute culpa ad voluptate aliquip ad ad laboris.',
      },
      quantity: 3,
    },
    {
      product: {
        id: 2,
        name: 'Steak meal',
        price: 200,
        image: require('../../assets/food-2.png'),
        description: 'Tempor aute culpa ad voluptate aliquip ad ad laboris.',
      },
      quantity: 2,
    },
  ],
};

并且我有一个输入来添加优惠券代码,当我添加优惠券代码会降低总价,所以如果我没有在商店中存储总计,该如何实现?并在添加此优惠券后渲染总价!

这是我的代码片段

reducer / index.js

import {
  ADD_COUPON,
  ADD_TO_CART,
  MINUS_FROM_CART,
  PLUS_FROM_CART,
  REMOVE_ITEM,
} from '../actions/types';

export default cartReducer = (state, action) => {
  console.log(action);
  switch (action.type) {
    case ADD_TO_CART: {
      return {
        cart: [
          ...state.cart,
          {
            product: action.productInfo,
            quantity: action.quantity,
          },
        ],
      };
    }
case PLUS_FROM_CART: {
  return {
    ...state,
    cart: state.cart.map(item => {
      if (item.product.id === action.productInfo.product.id) {
        return {
          ...item,
          quantity: action.quantity + 1,
        };
      }
      return item;
    }),
  };
}

case MINUS_FROM_CART: {
  return Object.assign({}, state, {
    cart: state.cart.map(item => {
      if (item.product.id === action.productInfo.product.id) {
        return Object.assign({}, item, {
          quantity:
            action.quantity <= 1 ? action.quantity : action.quantity - 1,
        });
      }
      return item;
    }),
  });
}

case REMOVE_ITEM: {
  return Object.assign({}, state, {
    cart: [
      ...state.cart.filter(
        ({product}) => product.id !== action.productInfo.product.id,
      ),
    ],
  });
}

case ADD_COUPON: { // here is
  console.log(state.cart);
  return {
    ...state,
    newTotal:
      state.cart.reduce(
        (total, item) => total + item.quantity * item.product.price,
        0,
      ) - 50,
  };
}

default:
  return state;


}

};

购物车屏幕

import React, {Component} from 'react';
import {
  Animated,
  Dimensions,
  FlatList,
  ScrollView,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from 'react-native';
import Swipeable from 'react-native-gesture-handler/Swipeable';
import Icon from 'react-native-vector-icons/Feather';
import {connect} from 'react-redux';
import CartIcon from '../components/CartIcon';
import CartItem from '../components/CartItem';
import {
  MinusFromCart,
  plusFromCart,
  removeItem,
} from '../store/actions/actions';

class CartsScreen extends Component {
  state = {
    delivery: 15,
    total: this.props.total,
    coupon: '',
  };

  applayCoupon = () => { // here is
    const {coupon} = this.state;
    if (coupon == 'Free') {
      this.props.addCoupon();
    }
  };
  handleIncreaseQuantity = (product, quantity) => {
    this.props.increaseQuantity(product, quantity);
  };
  handleDecreaseQuantity = (product, quantity) => {
    this.props.decreaseQuantity(product, quantity);
  };
  handleRemoveItem = product => {
    this.props.removeProduct(product);
  };

  render() {
    return (
      <View style={styles.container}>

        <View style={{marginBottom: 5}}>
          <View
            style={{
              borderColor: '#d7d7d7',
              margin: 15,
              borderWidth: 1,
              padding: 15,
              borderRadius: 10,
              flexDirection: 'row',
              justifyContent: 'space-between',
            }}>
            <TextInput
              value={this.state.coupon}
              style={{width: '80%'}}
              onChangeText={coupon => this.setState({coupon})}
              placeholder="Write coupon code"
            />
            <TouchableOpacity onPress={() => this.applayCoupon()}>
              <Text style={{color: '#f00'}}>Apply</Text>
            </TouchableOpacity>
          </View>
          <View
            style={{
              paddingVertical: 5,
              marginBottom: 5,
              flexDirection: 'row',
              justifyContent: 'space-between',
              paddingHorizontal: 15,
            }}>
            <Text style={{fontSize: 15}}>Subtotal</Text>
            <Text style={{fontSize: 15}}>{this.props.total.toFixed(2)}$</Text>
          </View>
          <View
            style={{
              paddingVertical: 5,
              marginBottom: 5,
              flexDirection: 'row',
              justifyContent: 'space-between',
              paddingHorizontal: 15,
            }}>
            <Text style={{fontSize: 15}}>Delivery Fee</Text>
            <Text style={{fontSize: 15}}>{this.state.delivery}$</Text>
          </View>

          <View
            style={{
              borderTopColor: '#ddd',
              borderTopWidth: 1,
              paddingVertical: 10,
              alignSelf: 'center',
            }}>
            <View
              style={{
                paddingVertical: 5,
                marginBottom: 5,
                flexDirection: 'row',
                justifyContent: 'space-between',
                paddingHorizontal: 15,
              }}>
              <Text style={{fontWeight: '700', fontSize: 18}}>Total</Text>
              <Text style={{fontWeight: '700', fontSize: 18}}>
                {this.props.total + this.state.delivery}
              </Text>
            </View>
            <Text
              style={{fontWeight: '700', paddingHorizontal: 15, fontSize: 18}}>
              after: {this.props.newTotal} $
            </Text>
            <TouchableOpacity
              style={{
                justifyContent: 'center',
                alignItems: 'center',
                padding: 15,
                borderRadius: 10,
                width: width - 20,
                backgroundColor: '#f10',
              }}>
              <Text style={{fontSize: 15, color: '#fff'}}>Checkout</Text>
            </TouchableOpacity>
          </View>
        </View>
      </View>
    );
  }
}

const mapStateToProps = state => {
  return {
    cartItem: state.cart,
    total: state.cart.reduce(
      (total, item) => total + item.quantity * item.product.price,
      0,
    ),
    newTotal: state.newTotal
  };
};

const mapDispatchToProps = dispatch => {
  return {
    increaseQuantity: (product, quantity) =>
      dispatch(plusFromCart(product, quantity)),
    decreaseQuantity: (product, quantity) =>
      dispatch(MinusFromCart(product, quantity)),
    removeProduct: product => dispatch(removeItem(product)),

    addCoupon: () => {
      dispatch({type: 'ADD_COUPON'});
    },
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(CartsScreen);

问题答案:

我的建议是不要在状态中存储冗余(派生的)信息。这意味着您不需要(也不应该!)将总数存储在状态中。这是一个问题的主要原因是,它给您的州提供了一个自相矛盾的机会……如果您州的total密钥不等于项目总数的总和,那么您将有一个大问题!

相反,您可以创建一个计算总数的函数,并在需要时简单地调用它。例如:

const calculateTotal = state => {
  let total = state.cart.reduce((total, item) => {
    return total + item.quantity * item.product.price 
  }, 0);
  // Assuming you just have one coupon, you could maintain a boolean in state
  if (state.hasCoupon) {
    total -= 50;
  }
  return total;
}

然后,在代码中需要获取总数的任何位置,都可以简单地使用此函数。在中包含这种功能并不罕见mapStateToProps

const mapStateToProps = state => ({
  total: calculateTotal(state);
});

如果最终遇到很多派生状态,则使用诸如Reselect之类的选择器库可能会带来一些好处,该选择器库可以帮助您构建从其他选择器派生的选择器,并实现
备忘录 以提高性能。



 类似资料:
  • 问题内容: 场景是,我要重定向用户或根据成功显示警报,在分派操作后显示错误回调。 下面是使用 redux-thunk 完成任务的代码 因为redux-thunk中的调度动作返回了Promise,所以响应起来很容易。 但是现在,我开始沉迷于redux- saga,试图弄清楚如何获得与上述代码相同的结果。由于Saga在不同的线程上运行,因此无法从上面的查询中获取回调。所以我只想知道你们是如何做到的。还

  • 问题内容: 我有一个操作可以更新应用程序的通知状态。通常,此通知将是错误或某种信息。然后,我需要在5秒钟后调度另一项操作,该操作会将通知状态恢复为初始状态,因此没有通知。其背后的主要原因是提供了5秒钟后通知自动消失的功能。 我没有使用并返回其他动作的运气,也找不到在线完成的方法。因此,欢迎提出任何建议。 问题答案: 不要陷入[认为图书馆应该规定如何做每件事的陷阱。如果您想在JavaScript中执

  • 我有一个更新应用程序通知状态的操作。通常,此通知将是一个错误或某种类型的信息。然后我需要在5秒后发送另一个动作,它将通知状态返回到初始状态,所以没有通知。这背后的主要原因是提供通知在5秒后自动消失的功能。 我没有使用并返回另一个操作,也找不到这是如何在网上完成的。所以欢迎任何建议。

  • 我试图结合反应路由器v4,反应,和redux。因为react-router跟踪URL,所以我选择将该状态块排除在redux模型之外。 但我仍然需要一种方法来在react路由器发生路由更改时调度redux操作。哪里是最好的地方? 我的第一次尝试是将它放在react路由器链接的onClick属性中: 其思想是,当用户单击链接时,dispatchAction()将更新redux状态,然后加载相册组件。

  • 问题内容: 我有一个plsql函数,我想从我的函数中调用另一个函数。我怎样才能做到这一点? 这是正确的方法吗? 问题答案: 函数必须返回一个值,否则您应该具有该函数的分配目标。

  • 问题内容: 我正在执行以下操作,但没有用 我正在调用一个返回游标的函数,所以我猜是问题所在 还有另一种方法吗? 问题答案: 我认为您的意思是参考光标。这是一个PL / SQL构造,用作指向查询返回的一组记录的指针。这意味着它必须由运行查询的客户端解释。例如,我们可以将Ref Cursor映射到JDBC或ODBC ResultSet。 您的基本声明当然没有错。这是一个类似于您自己的函数: 我可以在更