react-native - 当状态/ Prop 改变时, react native 动画部分列表跳到顶部

标签 react-native react-animated react-native-sectionlist

我正在使用部分列表组件在 React native 应用程序中构建一个 View ,它上面还有一个标题,它将显示有关列表的聚合数据。当您滚动时,标题 View 应该随着动画缩小。我的所有动画都运行良好,但是使用 onEndreached 添加无限滚动时会出现问题支柱。当添加新数据或状态/ Prop 更改时,它会跳到列表顶部。

为了使 SectionList 具有动画效果,我使用 Animated.createAnimatedComponent 将其包裹起来创建一个 <AnimatedSectionList />零件。当它被 Animated 包裹时,问题就出现了。

在下面链接的 gif 中,您可以看到当我向下滚动时它会跳到列表的顶部。这是状态发生变化并且我们开始获取更多数据的时候。 https://monosnap.com/file/2aH5iPF2XcygEz381bpHW9QGPGHA2Z

我试过使用 getItemLayout计算列表大小希望因为我读到当 react 不知道列表的高度时,它可能会跳动。

我还尝试使用 scrollTo 加载新数据后滚动到某个部分但这也不管用。我是用 componentDidUpdate 做的生命周期方法,但是 componentDidUpdate当新数据进来时,并没有被一致地调用。

这是我的代码。


const DataItem = [
  { name: "test name", value: "testvalue" },
  { name: "test name", value: "testvalue" },
  { name: "test name", value: "testvalue" },
  { name: "test name", value: "testvalue" },
  { name: "test name", value: "testvalue" }
];

const initialSections = [
  { title: "MY DETAILS", data: DataItem },
  { title: "MY COMMUNITY", data: DataItem },
  { title: "MY FAMILY", data: DataItem }
];

const styles = {
  item: {
    flex: 1,
    height: 50,
    marginTop: 1,
    backgroundColor: "#dddddd"
  },
  sectionHeader: {
    flex: 1,
    height: 20,
    marginTop: 1,
    backgroundColor: "#00ff00"
  }
};



class Edit extends Component {
  constructor(props) {
    super(props);

    this.state = {
      scrollEnabled: true,
      scrollY: new Animated.Value(0),
      sections: initialSections,
      refreshing: false
    };


  _renderSectionHeader(section) {
    return (
      <View style={styles.sectionHeader}>
        <Text> {section.title} </Text>
      </View>
    );
  }

  _renderItem(item) {
    return (
      <View style={styles.item}>
        <Text>{item.name}</Text>
      </View>
    );
  }


  handleStateButton() {
    this.setState({ refreshing: true });
  }

  fetchMoreData() {
    this.setState({ refreshing: true });

    const newData = [...this.state.sections, ...initialSections];

    setTimeout(
      function() {
        this.setState({ sections: newData, refreshing: false });       }.bind(this),
      2000
    );
  }

  render() {
    const backgroundScrollY = this.state.scrollY.interpolate({
      inputRange: [0, 224],
      outputRange: [0, -50],
      extrapolate: "clamp"
    });

    const backgroundScrollHeight = this.state.scrollY.interpolate({
      inputRange: [0, 224],
      outputRange: [1, 0.75],
      extrapolate: "clamp"
    });

    const listScrollY = this.state.scrollY.interpolate({
      inputRange: [0, 224],
      outputRange: [0, -10],
      extrapolate: "clamp"
    });

    const infoOpacity = this.state.scrollY.interpolate({
      inputRange: [0, 0.5, 150],
      outputRange: [1, 1, 0],
      extrapolate: "clamp"
    });

    const AnimatedSectionList = Animated.createAnimatedComponent(SectionList);

    return (
      <View
        style={{
          flex: 1,
          //   alignItems: "flex-start",
          flexDirection: "column"
        }}
      >
        <Animated.View
          style={[
            {
              position: "relative",
              // flex: 1,
              // alignSelf: "flex-start",
              top: 0,
              minHeight: 200,
              height: 300,
              backgroundColor: "#ddee99",
              border: "1px solid #0000FF",
              justifyContent: "center",
              alignItems: "center"
            },
            { transform: [{ scaleY: backgroundScrollHeight }] }
          ]}
        >
          <Animated.Image
            source={{
              uri:
                "https://images.unsplash.com/photo-1558901591-3a5f333830dd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80"
            }}
            style={[
              { position: "absolute", backgroundColor: "#cccccc" },
              { transform: [{ translateY: backgroundScrollY }] }
            ]}
            blurRadius={1.5}
          />

          <Text>{this.state.refreshing && `Fetching data`}</Text>

          <Button onPress={this.fetchMoreData} title="Get More Data" />
          <Button onPress={this.handleStateButton} title="Changing State" />
        </Animated.View>

        <AnimatedSectionList
          ref={ref => (this.sectionListRef = ref)}
          bounces={false}
          scrollEnabled={this.state.scrollEnabled}
          style={[
            { position: "relative" },
            { transform: [{ translateY: listScrollY }] }
          ]}
          onScroll={Animated.event(
            [{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
            { listener: this._onScroll.bind(this) }
          )}
          sections={this.state.sections}
          renderSectionHeader={({ section }) =>
            this._renderSectionHeader(section)
          }
          ListHeaderComponent={() => (
            <View
              style={{
                flex: 1,
                flexDirection: "row",
                alignItems: "center",
                height: 40,
                backgroundColor: "#ff00ff"
              }}
            >
              <Text>List Header</Text>
            </View>
          )}
          ListFooterComponent={() => (
            <View
              style={{
                flex: 1,
                flexDirection: "row",
                alignItems: "center",
                height: 80,
                backgroundColor: "#FF0"
              }}
            >
              <Text>List Footer</Text>
            </View>
          )}
          getItemLayout={this.getItemLayout}
          renderItem={({ item }) => this._renderItem(item)}
          keyExtractor={(item, index) => index}
          stickySectionHeadersEnabled={true}
          onEndReachedThreshold={0.75}
          onEndReached={d => {
            this.fetchMoreData();
          }}
        />
      </View>
    );
  }
}


我希望当 state 或 props 发生变化时,列表会保持在当前滚动位置,但相反,它会跳到顶部,从而破坏无限滚动的目的。

如果您对解决此问题的最佳方式有任何想法,我们将不胜感激。

最佳答案

我把

const AnimatedSectionList = Animated.createAnimatedComponent(SectionList);

离开了类(class),停止了跳级

关于react-native - 当状态/ Prop 改变时, react native 动画部分列表跳到顶部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56334026/

相关文章:

javascript - 在 React Native 部分列表中过滤数据

react-native - 使用 SectionList 时无法读取未定义的属性 'length'

javascript - 如何在 if 语句中渲染某些内容 React Native

javascript - react native : Can't get (apparently async) function to finish before moving on

listview - React Native动态ListView主细节

reactjs - 为什么只有一个 react native 并行动画在运行而另一个没有运行?

react-native - uri 的值无法从 double 类型转换为字符串类型

reactjs - React Native Animated 来缩放图像

animation - 在 React Native Animated 中使用 useNativeDriver 时出错

typescript - react native 部分列表 : What are the correct TypeScript types