更新状态数组后,React 本机没有重新渲染



我有以下代码(完整示例(:

import React, { useState, useEffect } from 'react';
import { SafeAreaView, View, Button, StyleSheet, Animated } from 'react-native';
import { PanGestureHandler, State } from 'react-native-gesture-handler';
const App = () => {
const [blocks, setBlocks] = useState([]);
const CreateBlockHandler = () => {
let array = blocks;
array.push({
x: new Animated.Value(0),
y: new Animated.Value(0)
});
setBlocks(array);
RenderBlocks();
};
const MoveBlockHandler = (index, event) => {
Animated.spring(blocks[index].x, { toValue: event.nativeEvent.x }).start();
Animated.spring(blocks[index].y, { toValue: event.nativeEvent.y }).start();
};
const RenderBlocks = () => {
return blocks.map((item, index) => {
return (
<PanGestureHandler key={index} onGestureEvent={event => MoveBlockHandler(index,event)}>
<Animated.View style={[styles.block, {
transform: [
{ translateX: item.x },
{ translateY: item.y }
]
}]} />
</PanGestureHandler>
)
});
};

return (
<SafeAreaView style={styles.container}>
<View style={styles.pancontainer}>
<RenderBlocks />
</View>
<Button title="Add block" onPress={CreateBlockHandler} />
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
pancontainer: {
width: '95%',
height:'75%',
borderWidth: 1,
borderColor: 'black'
},
block: {
width: 50,
height: 50,
backgroundColor: 'black'
}
});
export default App;

这段代码有什么作用?这是一个大正方形,下面有一个按钮。当我点击按钮时,在大方块中制作了一个新的黑色方块(50x50(。我通过创建一个新的数组元素(数组 = 块(来做到这一点。这是在函数 CreateBlockHandler中完成的。这无法正常工作!

函数 MoveBlockHandler使小方块可移动。这行得通!

什么不起作用?当我创建一个新的黑色方块时,黑色方块不会在屏幕上呈现。只有当我刷新时,才会渲染正方形。正方形是通过 CreateBlockHandler 创建的,因为当我在该函数中执行控制台.log(块(时,我可以看到添加了一个新的数组元素。

如何强制此代码对所有数组元素进行完全重新渲染?我试图将正方形的渲染包装在一个单独的函数(RenderBlocks(中,每次制作新的正方形时我都会调用这个函数(CreateBlockHandler的最后一行(。调用该函数(我可以使用控制台.log((检查这一点(,但没有呈现正方形。

当您将blocks分配给array时,复制的引用gete会改变状态,因此它不会在setState上重新呈现。

const CreateBlockHandler = () => {
let array = [...blocks];
array.push({
x: new Animated.Value(0),
y: new Animated.Value(0)
});
setBlocks(array);
RenderBlocks

您的代码存在多个问题。

正如 kooskoos 指出的那样,您的状态在引用上保持相等(它是相同的数组,只是元素会改变(。这不会触发重新渲染。

此外,您正在操作App组件的状态。RenderBlocks组件的 props 和状态保持不变,这意味着它们不需要重新渲染。由于该组件是一个匿名函数,并且在每次渲染App时都会重新创建,因此无论如何它可能会被重新渲染。

此外,您直接调用RenderBlocks,它看起来像一个组件。这是不必要的,在这里什么也做不了,但如果它有任何钩子,它会导致问题。

您可能还应该遵守组件大写和回调蛇案例大写的约定。

最新更新