Позиции ScrollView перезапускаются при повторной отрисовке (обновлении) дочернего компонента - PullRequest
2 голосов
/ 08 мая 2020

У меня проблема (вероятно, это то, что я игнорирую в цикле рендеринга) с сохранением позиции двух разных видов прокрутки при обновлении некоторых из его дочерних компонентов.

У меня есть иерархия представлений, которая похожа на:

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

Один из возможных подходов к решению этой проблемы - иметь механизм, который позволяет мне сохранять позицию прокрутки перед обновлением. Но это сильно усложнит коммуникацию между компонентами, et c. Кстати, обновление статуса ячейки осуществляется через 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>

Панель доступности - одна из дочерних

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

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 11 мая 2020

Я думаю, что общая идея сохранения позиции прокрутки вашего scrollview хороша.

Я думаю, что тот факт, что ваше состояние сбрасывается до 0, вероятно, происходит из-за Redux (не уверен, однако, можете ли вы уточнить, как ваш компонент подключен к redux?). Я не так хорошо знаком с хуками, но в компоненте React Class я бы попытался сохранить позицию прокрутки в негосударственном свойстве класса. Может быть, сохранить его в переменной вне вашего функционального компонента?

Затем в обработчике для управления обновлениями ячеек вы можете убедиться, что ваш scrollview прокручивается до сохраненной позиции (используя ScrollView.scrollTo () , с опцией {animated: false}, чтобы анимация не была видна пользователю)

2 голосов
/ 17 мая 2020

ScrollView не сбрасывает позицию прокрутки из-за дочерних обновлений, независимо от того, используете ли вы Redux или нет. Вам не нужно пытаться исправить это обходными путями, такими как сохранение текущих позиций прокрутки. Скорее просто выясните, что не так с вашей настройкой

Трудно сказать, потому что вы не предоставили свой фактический код, но я почти уверен, что один или оба ScrollView повторно монтируются при обновлениях (старый ScrollView удален, а новый один создается вместо него с собственной позицией прокрутки). Вероятно, вы объявляете новые компоненты внутри функции рендеринга, поэтому React будет просто перемонтировать их каждый раз

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...