首页 > 解决方案 > ScrollView 位置在子组件重新渲染时重新启动(更新)

问题描述

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

我有一个视图层次结构,例如:

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

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

我尝试使用保存 scrollOffset (x,y)useState但如果我更改某些单元格,状态将重置为 (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 处理的。

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

---- UPDATE 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>

可用性面板是其中一个孩子

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>
  )
}

提前致谢。

标签: reactjsreact-nativereact-reduxscrollview

解决方案


ScrollView 不会因为子更新而重置滚动位置,无论您是否使用 Redux。您无需尝试使用保存当前滚动位置等变通方法对其进行修补。而是找出您的设置有什么问题

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


推荐阅读