是否有一种方法来防止自动重新渲染时,导致事件在一个SectionList?



这是我的返回函数,它包含了渲染器中的所有组件。每次我按下Sectionlist中的footerComponent,整个屏幕都会重新呈现,并导致自动滚动到位置0。

return (
<SafeAreaView style={styles.container}>
<ImageBackground
source={require("../assets/stars.gif")}
style={{
width: Dim.width,
height: Dim.height,
}}
resizeMode="repeat"
>
{files ? <List /> : null}
<CustomModal
visible={visible}
onPressIn={() => startRecording()}
onPressOut={() => stopRecording()}
onExitPress={() => setVisible(false)}
onConfirm={() => sendToStorage(ID, len)}
disabled={!strgUri}
onDismiss={() => setRecording(null)}
modalButton={[
styles.modal,
pressed
? { backgroundColor: Colors.clay }
: { backgroundColor: Colors.aegean },
]}
progress={progress}
loadingVisible={sending}
/>
</ImageBackground>
</SafeAreaView>
);

这是我的Animated SectionList组件

const NewSectionList = Animated.createAnimatedComponent(SectionList);
const List = React.forwardRef((ref, props) => {
const respondRef = useRef();
const scrollRef = useRef().current;
function scrollToSection() {
if (respondRef.current) {
respondRef.current.measure((x, y, width, height, px, py) => {
console.log("height: ", height);
console.log("y: ", y);
setHeight(py);
});
console.log("scrolling to: ", height);
if (height != 0) {
setTimeout(() => {
console.log("wait height: ", height);
console.log("dim height: ", Dim.height);
console.log("1 height: ", Dim.height - height + Dim.height);
scrollRef?.scrollTo({
x: 0,
y: Dim.height - height + Dim.height,
animated: true,
});
}, 1000);
}
}
}
useEffect(() => {
scrollToSection();
});
const yVal = fadeAnim.interpolate({
inputRange: [0, 1],
outputRange: [900, 0],
});
const animStyle = {
transform: [
{
translateY: yVal,
},
],
};
return(
<Animated.View style={[animStyle]}>
<NewSectionList
ref={scrollRef}
stickySectionHeadersEnabled={false}
sections={files}
keyExtractor={(item) => item.id}
style={{
marginLeft: 10,
marginBottom: 110,
}}
renderItem={({ item }) => (
<View style={styles.cardContainer}>
<View
style={{
alignSelf: "flex-start",
position: "absolute",
marginTop: 5,
}}
>
<Text p4 dusk>
{new Date(item.timestamp).toDateString()}
</Text>
</View>
<TouchableOpacity
onPress={() => visitProfile(item.name, item.email)}
>
<Text p2 aegean>
{item.name}
</Text>
</TouchableOpacity>
<View styles={styles.cardTap}>
<TouchableNativeFeedback
onPress={() => {
playFile(item.url, item.id);
}}
>
<AntDesign name="stepforward" size={40} color={Colors.led} />
</TouchableNativeFeedback>
</View>
</View>
)}
renderSectionHeader={({
section: {
information,
origin,
userOrigin,
emailOrigin,
origID,
originDate,
},
}) => (
<View style={styles.headerContainer}>
<View
style={{
alignSelf: "flex-start",
position: "absolute",
marginTop: 5,
}}
>
<Text p3 led>
{new Date(originDate).toDateString()}
</Text>
</View>
<View style={styles.holder}>
<TouchableOpacity
onPress={() => visitProfile(userOrigin, emailOrigin)}
>
<Text h4 night>
{userOrigin}
</Text>
</TouchableOpacity>
</View>
<View style={styles.outerInfo}>
<Text p3 dusk style={styles.textInfo}>
{information ? information : ""}
</Text>
</View>
<View styles={styles.cardTap}>
<TouchableNativeFeedback
onPress={() => {
playFile(origin, origID);
}}
>
<AntDesign
name="stepforward"
size={40}
color={Colors.night}
/>
</TouchableNativeFeedback>
</View>
</View>
)}
renderSectionFooter={({ section: { docId, dataLen } }) => (
<TouchableOpacity
ref={respondRef}
style={styles.notPressed}
onPress={() => {
setVisible(true);
scrollToSection();
setID(docId);
setLen(dataLen);
}}
>
<Text p2 white>
add to convo
</Text>
</TouchableOpacity>
)}
refreshControl={<RefreshControl onRefresh={() => getData()} />}
/>
</Animated.View>
);
});

我试图实现一个scrollTo()方法函数到按下按钮的位置,但这更多的是一个hack而不是一个真正的解决方案,因为它将保持重新渲染和滚动。此外,我试图激活的模态在它内部有其他有状态的组件,导致更多的重新渲染。另一个尝试的修复是试图记住模态,但是官方文档建议过早优化不是一个真正的解决方案,并将导致更多的错误。谢谢你。

创建新的useEffect来调试当页面重新渲染时files是否总是改变:

console.log('Screen in rerendered');
useEffect(() => {
console.log('`files` is changed', JSON.stringify(files, undefined, 2));
}, [files]);

当你按下footerComponent时,文件不应该被改变。

你可能还想用memo()包裹你的<Animated.View></Animated.View>,以防止在它自己的组件中重新渲染,如果道具仍然相等。

好的,所以我的问题的解决方案实际上只是渲染CustomModal组件在我的列表组件,所以当我需要显示模态,我可以在列表组件中设置状态,而不是发送给父组件。将它发送给父组件时,每次我将状态设置为不同的值时,都会在子组件中重新渲染。所以一般来说,如果你想防止兄弟组件之间的重新渲染,只需在带有state的组件中渲染依赖于状态的组件。

最新更新