正在重新渲染(更新)子组件上重新启动的ScrollView位置



在更新两个不同滚动视图的一些子组件时,我在维护其位置时遇到了问题(这可能是我在渲染周期中忽略的问题(。

我有一个层次的观点,就像:

<ScrollView vertical scrolling ability>
...
<ScrollView horizontal and vertical scrolling ability>
...
<Matrix>
<Cell updateCellStatusHandler={handler}>
</Matrix>
...
</ScrollView>
</ScrollView>

因此,内部单元格的更新正在重置单元格状态更新的两个滚动,这会产生一种超级奇怪的体验,用户必须向下/向左/向右滚动才能继续与我所拥有状态的单元格矩阵交互。

我曾尝试使用useState保存scrollOffset(x,y(,但如果我更改某个单元格,则状态将重置为(0,0(,这是我的初始状态。

const [scrollOffset, setScrollOffset] = useState({
scrollX: 0,
scrollY: 0,
})

但没有运气。

<ScrollView
{...props}
scrollEventThrottle={16}
ref={scrollReference}
// tslint:disable-next-line: jsx-no-lambda
onScroll={event => {
setScrollOffset({
scrollX: event.nativeEvent.contentOffset.x,
scrollY: event.nativeEvent.contentOffset.y,
})
}}
onScrollEndDrag={event => {
console.log(event.nativeEvent.contentOffset.y)
console.log(event.nativeEvent.contentOffset.x)
}}
>
{props.children}
</ScrollView>

解决这个问题的一种可能方法是使用一种机制,允许我在更新之前保存滚动位置。但这会使组件之间的通信等变得复杂。顺便说一下,小区状态更新是通过Redux处理的。

如果你们中的一些人能给你们带来一些光明,那就太好了。

----更新1(添加了面板组件的代码(----

父组件是:

<View style={styles.container}>
<CustomScrollView enableResetScrollToCoords={false}>
<Section>
<WhiteContainer>
<View style={styles.rateContainer}>
<DescriptionTextStatus
statusText={getMessageForRate(availabilityRate)}
descriptionText={getDescriptionForRate(
availabilityRate,
isTeacher,
)}
icon={getImageForRate(availabilityRate)}
/>
</View>
</WhiteContainer>
</Section>
{!loggedUserIsTeacher() && <AvailabilityStart />}
<AvailabilityPanel />
<AvailabilityStatus />
<AvailabilityButtonSave />
</CustomScrollView>
</View>

可用性面板是child的之一

export const AvailabilityPanel: React.FunctionComponent<{}> = () => {
const panel: Cell[][] = useSelector((state: ReduxStore) => {
return get(state.entities, 'availability.panel', undefined)
})
if (panel === undefined) {
return <Nothing />
}
return (
<Section>
<WhiteContainer>
<LinearGradient
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
colors={[Palette.White, Palette.White68]}
>
<View style={styles.rateContainer}>
<DescriptionTextStatus
statusText={strings.warning}
descriptionText={strings.selectionMessage}
icon={'clock'}
/>
<View style={styles.separator} />
</View>
<View style={styles.container}>
<ScrollView
style={styles.scrollView}
directionalLockEnabled={false}
horizontal={true}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
>
<View style={styles.contentContainer}>
<View style={styles.weekdaysContainer}>
<PanelHeader weekdays={weekdays} />
</View>
<View style={styles.rowsContainer}>
{hours.map((hourLabel: string, index: number) => {
return (
<PanelRow
key={index}
hourLabel={hourLabel}
hoursRow={panel[index]}
rowIndex={index}
/>
)
})}
</View>
</View>
</ScrollView>
</View>
</LinearGradient>
</WhiteContainer>
</Section>
)
}

提前谢谢。

无论是否使用Redux,ScrollView都不会因为子更新而重置滚动位置。您不需要尝试使用诸如保存当前滚动位置之类的变通方法来修补它。相反,只要弄清楚你的设置有什么问题

很难说,因为你没有提供实际的代码,但我很确定一个或两个ScrollView都会在更新时重新加载(旧的ScrollView会被删除,新的ScrollView会在它自己的滚动位置上创建(。很可能您在render函数中声明了新的组件,所以React每次都会重新安装它们

我认为保存滚动视图的滚动位置的总体想法是好的。

我认为您的状态重置为0的事实可能是由于Redux造成的(但不确定,您能否准确地确定您的组件是如何连接到Redux的?(。我对Hooks不太熟悉,但在React Class组件中,我会尝试将滚动位置保存在该类的非状态属性中。也许可以将其保存在功能组件之外的变量中?

然后,在管理单元格更新的处理程序中,您可以确保滚动视图滚动到您保存的位置(使用scrollview.scrollTo((,带有{animated: false}选项,这样用户就看不到动画(

最新更新