- 问题:**
在ReactNative中使用ScrollView进行水平分页时,它会重新呈现所有子组件,但我希望保留子组件的某些局部输入字段和局部变量的状态值。
在下面的代码中,如果我正在更新NotesSection中的TextInput,但希望扫回BatchSection以查看一些元数据,则代码将重新呈现NotesSection并重置保存文本值的本地状态。
- 诊断:**
我对React和React Native还很陌生,但我最好的猜测是,这是由于父状态变量"horizontalPos"导致的,该变量使用整数来反映焦点所在的页面。这只是在ProductHeader组件中使用,以突出显示彩色bottomBorder,向用户显示屏幕顶部的一种小"菜单"。"horizontalPos"状态可以通过两种方式更新:
1.第一种是在ProductHeader中单击所需标题 (TouchableOpacity) 时,这会触发状态更改并使用useRef自动移动ScrollView。
1.第二个选项是当用户在ScrollView上滑动时,使用OnScroll运行函数"handleHorizontalScroll",该函数反过来使用contentOffset.x中的简单数学设置"horizontalPos"状态。
- 问题/解决方案:**
如果"horizontalPos"状态是INSIDE ProductHeader,我怀疑这会解决问题,但我无法思考如何做到这一点,因为我不相信有可能基于父组件中的更改将函数传递给子组件。
我依赖于在主ScrollView上注册OnScroll,其余组件同样必须位于主ScrollView内部,但我不希望每次"horizontalPos"状态更新时都重新呈现它们。
- 代码:**
const ProductScreen = (props) => {
const [horizontalPos, setHorizontalPos] = useState(0)
const scrollRef = useRef()
const toggleHorizontal = (page) => {
setHorizontalPos(page)
scrollRef.current.scrollTo({x:page*width, y:0, animated:false})
}
const handleHorizontalScroll = (v) => {
const pagination = Math.round(v.nativeEvent.contentOffset.x / width)
if (pagination != horizontalPos){
setHorizontalPos(pagination)
}
}
const ProductHeader = () => {
return(
<View style={styles.scrollHeaderContainer}>
<TouchableOpacity style={[styles.scrollHeader, horizontalPos == 0 ? {borderColor: AppGreenDark,} : null]} onPress={() => toggleHorizontal(0)}>
<Text style={styles.scrollHeaderText}>Meta Data</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.scrollHeader, horizontalPos == 1 ? {borderColor: AppGreenDark,} : null]} onPress={() => toggleHorizontal(1)}>
<Text style={styles.scrollHeaderText}>{"Notes"}</Text>
</TouchableOpacity>
</View>
)
}
return (
<View style={styles.container}>
<ProductHeader/>
<ScrollView
ref={scrollRef}
decelerationRate={'fast'}
horizontal={true}
showsHorizontalScrollIndicator={false}
snapToInterval={width}
onScroll={handleHorizontalScroll}
scrollEventThrottle={16}
disableIntervalMomentum={true}
style={{flex: 1}}
>
<View style={[styles.horizontalScroll]}>
<View style={styles.mainScrollView}>
<BatchSection/>
</View>
<ScrollView style={styles.notesScrollView}>
<NotesSection/>
</ScrollView>
</View>
</ScrollView>
</View>
)
}
1条答案
按热度按时间t3irkdon1#
如您所述,更新
ProductScreen
内部的horizontalPos
状态将导致整个屏幕重新呈现,这不是预期行为。为了避免这种情况,让我们按如下方式重构代码:
我希望这将阻止整个屏幕重新呈现和维护分页。