react-native - 已调度操作并更新状态,但未渲染 UI 组件
问题描述
谁可以支持我的问题:调度操作确实会改变预期的状态。但是发出问题的组件不会重新渲染。当我简单地保存组件时,它当然会重新渲染并显示所需的效果。
这是我的文件:
动作.js
export const TOGGLE_PRODUCT = "TOGGLE_PRODUCT";
export const INCREMENT = "INCREMENT";
//ACTION CREATER FUNCTIONS
export const toggleProduct = (id) => {
return {
type: TOGGLE_PRODUCT,
productId: id,
};
};
减速器.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;
组件.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;
解决方案
这些行是问题所在:
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,
};
那就是改变现有的状态,你绝不能在 Redux reducer 中改变状态!.
要解决此问题,您需要制作Products
数组和toggledProduct
对象的副本,更新副本并返回它们。
话虽如此,更好的选择是使用我们官方的 Redux Toolkit 包,这是我们推荐的编写 Redux 逻辑的方法。它允许您编写“变异”逻辑,将其转换为安全且正确的不可变更新。
createSlice
这是使用 Redux Toolkit 的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;
}
}
})
推荐阅读
- python-3.x - 将 Pandas 行中的向量值转换为 python 中的新行
- api - 如何使用 Google Vault API 管理 gmail 保留规则?
- c++ - 使用 std::function 作为参数时,C++11 模板推导失败
- python - 氢原子的薛定谔方程:为什么 numpy 显示错误的解决方案而 scipy 不是?
- ios - 尝试附加结构数组时发生变异错误
- newrelic - 如何使用 NewRelic NRQL 为多个应用程序创建通用策略?
- php - Doctrine - 按 utf-8 排序规则排序
- neo4j - Neo4j ServiceUnavailable:无法在 5000 毫秒内建立连接
- c++ - 作业问题 - C++ 更新已识别的变量
- sql - 在动态查询的行之间选择