【问题标题】:Action dispatched and state updated, but no render of the UI component已调度操作并更新状态,但未渲染 UI 组件
【发布时间】:2021-01-18 23:27:52
【问题描述】:

谁能支持我的问题:调度操作确实会按预期改变状态。但是发出问题的组件不会重新渲染。当我简单地保存组件时,它当然会重新渲染并显示所需的效果。

这是我的文件:

actions.js

export const TOGGLE_PRODUCT = "TOGGLE_PRODUCT";
export const INCREMENT = "INCREMENT";

//ACTION CREATER FUNCTIONS
export const toggleProduct = (id) => {
  return {
    type: TOGGLE_PRODUCT,
    productId: id,
  };
};

reducer.js

import { PRODUCTLIST } from "../../data/dummydata";
import { TOGGLE_PRODUCT } from "../actions/products";

const initialState = {
  allProducts: PRODUCTLIST,
};

const productReducer = (state = initialState, action) => {
  switch (action.type) {
    case TOGGLE_PRODUCT:
      const Products = state.allProducts;
      const toggledProduct = Products.find((el) => el.id === action.productId);
      if (toggledProduct.status === false) {
        toggledProduct.status = true;
      } else {
        toggledProduct.status = false;
      }
      console.log("Neue Products: ", Products);
      return {
        allProducts: Products,
      };
    default:
      return state;
  }
};

export default productReducer;

component.js

import { useSelector, useDispatch } from "react-redux";
import React, { useEffect, useCallback } from "react";
import { Text, View, Button, FlatList, StyleSheet } from "react-native";

import Product from "../components/Product";
import { toggleProduct } from "../store/actions/products";
import { increment } from "../store/actions/products";

const ShoppingListScreen = (props) => {
  const dispatch = useDispatch();

  const toggleProductHandler = useCallback(
    // useCallback verhindert infinite loop
    (id) => {
      dispatch(toggleProduct(id));
    },
    []
  );

  const Products = useSelector((state) => state.product.allProducts);

  return (
    <View style={styles.screen}>
      <FlatList
        data={Products}
        renderItem={({ item }) => (
          <View
            style={
              item.status === true ? styles.elementselected : styles.element
            }
          >
            <Product
              style={styles.text}
              id={item.id}
              product={item.product}
              department={item.department}
              status={item.status}
              onClick={() => toggleProductHandler(item.id)}
            />
          </View>
        )}
      />
      <View style={styles.button}>
        <Button
          title="FERTIG"
          onPress={() => {
            props.navigation.goBack();
          }}
        />
        {/* <Button
                    title='Stand "cartRewe" '
                    onPress={() => {
                        props.testFunction1();
                    }}
                />
                <Button
                    title='Stand "planRewe" '
                    onPress={() => {
                        props.testFunction2();
                    }}
                /> */}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  screen: {
    backgroundColor: "#fafafa",
    flex: 1,
    justifyContent: "flex-start",
  },
  element: {
    backgroundColor: "#ddd",
    borderWidth: 2,
    borderColor: "#bbb",
    borderRadius: 20,
    marginVertical: 5,
    marginHorizontal: 25,
  },
  elementselected: {
    backgroundColor: "#a0ffa0",
    borderWidth: 3,
    borderColor: "#64ff64",
    borderRadius: 20,
    marginVertical: 5,
    marginHorizontal: 25,
  },
  text: {
    color: "#333",
    // fontSize: 22,
    // marginHorizontal: 10
  },
  button: {
    marginVertical: 24,
  },
});

export default ShoppingListScreen;

【问题讨论】:

    标签: react-native react-redux action render dispatch


    【解决方案1】:

    这些是问题所在:

    const Products = state.allProducts;
          const toggledProduct = Products.find((el) => el.id === action.productId);
          if (toggledProduct.status === false) {
            toggledProduct.status = true;
          } else {
            toggledProduct.status = false;
          }
          return {
            allProducts: Products,
          };
    

    这是在改变现有状态,you must never mutate the state in a Redux reducer!

    要解决此问题,您需要make copies of the Products array and the toggledProduct object,更新副本,然后返回。

    话虽如此,更好的选择是to use our official Redux Toolkit package,这是我们推荐的编写 Redux 逻辑的方法。它允许您编写“变异”逻辑,将其转换为安全且正确的不可变更新。

    这是使用 Redux Toolkit 的 createSlice API 的样子:

    
    const productsSlice = createSlice({
      name: 'products',
      initialState: {allProducts: []},
      reducers: {
        productToggled(state, action) {
          const toggledProduct = state.allProducts.find(e => e.id === action.payload);
          // This "mutating" syntax _only_ works inside Redux Toolkit's createSlice/createReducer!
          toggledProduct.status = !toggledProduct.status;
        }
      }
    })
    

    【讨论】:

      【解决方案2】:

      不改变状态对象是完全有意义的。由于我现在确实想为这个问题实现一个进一步的包,我按照建议修改了我的源代码。出于任何原因,如果没有手动保险箱,我的组件仍然不会重新渲染。这段代码怎么样,还有什么问题?

      reducer.js

      import { PRODUCTLIST } from "../../data/dummydata";
      import { TOGGLE_PRODUCT } from "../actions/products";
      
      const initialState = {
        allProducts: PRODUCTLIST,
      };
      
      const productReducer = (state = initialState, action) => {
        switch (action.type) {
          case TOGGLE_PRODUCT:
            const newProducts = state.allProducts;
            const toggledProduct = newProducts.findIndex(
              (el, idx) => el.id === action.productId
            );
            if (newProducts[toggledProduct].status === false) {
              newProducts[toggledProduct].status = true;
            } else {
              newProducts[toggledProduct].status = false;
            }
            return {
              ...state,
              newProducts,
            };
          default:
            return state;
        }
      };
      
      export default productReducer;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多