首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FlatList ref scrollToIndex不是函数

FlatList ref scrollToIndex不是函数
EN

Stack Overflow用户
提问于 2019-12-13 06:50:55
回答 5查看 10.2K关注 0票数 5

我面对的似乎是一个长期存在的问题,在反应本土。

我使用的是RN版本0.59的世博会SDK35。我还没有更新到世博会SDK36 /RN0.60,因为有大量的代码库,但我可以更新,如果这弥补了我的问题的解决方案。

我有一个Animated.View组件,它有一个FlatList子组件,我无法使用应该在FlatList引用上可用的静态方法(特别是scrollToIndex())。请参阅下一个示例代码:

代码语言:javascript
复制
class Example extends React.Component{
    constructor(props){
        super(props);
        this.myRef = null;
    }

    componentDidUpdate = () => {
        /*
            somewhere in code outside this class, a re-render triggers
            and passes new props to this class.
            I do have props change detection, and some more other code,
            but I have removed it in order to minimize the code example here
        */

        // This call throws:
        // TypeError: undefined is not a function (near '...this._scrollRef.scrollTo...')
        this.myRef.scrollToIndex({
            animated: true,
            index: 1,
            viewOffset: 0,
            viewPosition: 0.5
        });

        // Other suggested solution from SO
        // This also throws:
        // TypeError: _this.myRef.getNode is not a function. (In '_this.myRef.getNode()', '_this.myRef.getNode' is undefined)
        this.myRef.getNode().scrollToIndex({
            animated: true,
            index: 1,
            viewOffset: 0,
            viewPosition: 0.5
        });
    }
    render = () => <Animated.View style={{ /* ... some animated props */ }}>
        <FlatList ref={(flatListRef) => { this.myRef = flatListRef; }}
            // more FlatList related props
        />
    </Animated.View>
}

我尝试使用Animated.FlatList,但仍然抛出与上面的代码示例相同的错误。

我还尝试在接收到的findNodeHandle()参数上使用本机的flatListRef实用程序函数,但它返回null

我发现相同的问题在过去多次张贴在堆栈溢出,大多数没有答案,或对我不起作用。这些帖子也有点老(一年左右),这就是为什么我再次为同样的问题张贴。

有人能找到解决这个问题的办法吗?

编辑:可能的解决办法

当我在处理代码时,我尝试使用ScrollView组件而不是FlatList --而scrollTo方法可以工作!

这些变化只发生在FlatList - ScrollView特定的道具上(因此,对于ScrolLView,它将是childs而不是data={[...]}renderItem={()=>{ ... }}等),以及componentDidMount中的scrollToIndex方法,后者被scrollTo所取代。

类的呈现方法(带有ScrollView )现在看起来如下所示:

代码语言:javascript
复制
    render = () => <Animated.View style={{ /* ... some animated props */ }}>
        <ScrollView ref={(flatListRef) => { this.myRef = flatListRef; }}>
            {/*
                this.renderItem is almost the same as the
                renderItem method used on the FlatList
             */}
             { this.state.dataArray.map(this.renderItem) }
        </ScrollView>
    </Animated.View>

请注意,ScrollView没有scrollToIndex()方法,因此您将不得不手动跟踪子位置,并可能实现自己的scrollToIndex方法。

我并不是回答我的问题,因为根本的问题仍然存在。但作为一种解决办法,也许你可以和它一起结束.

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2020-10-06 19:15:29

TL;DR;

代码语言:javascript
复制
this.myRef = React.createRef();
this.myRef.current.doSomething(); // note the use of 'current'

长篇版本:

虽然我的尝试背后的想法是正确的,但我原来的帖子中的错误似乎相当愚蠢。为了我的辩护,医生们还不清楚(可能.)。不管怎样..。

React.createRef返回一个有几个字段的对象,所有这些字段对开发人员毫无用处(后面的React使用)--除了一个:current。此支柱保存对ref附加到的基础组件的当前引用。主ref对象不能用于我原来的问题中的目的。

相反,我应该这样正确地使用ref:

代码语言:javascript
复制
this.myRef.current.scrollToIndex(...)

等等,别撞车

myRef对象和current字段都将是null,如果组件尚未挂载,以后任何时候都已卸载,或者由于某种原因无法将ref附加到它。您可能知道(或者稍后会发现),null.something会抛出一个错误。因此,为了避免这种情况:

代码语言:javascript
复制
if ((this.myRef !== null) && (this.myRef.current !== null)){
    this.myRef.current.scrollToIndex(...);
}

额外保险

如果尝试将未定义的值作为ref上字段上的函数调用,则代码将崩溃。如果错误地在多个组件上重用相同的引用,或者附加它的组件没有该方法(即View没有scrollTo方法),就会发生这种情况。要解决这个问题,您有两个解决方案:

代码语言:javascript
复制
// I find this to be the most elegant solution
if ((this.myRef !== null) && (this.myRef.current !== null)) {
    if (typeof this.myRef.current.scrollToIndex === "function") {
        this.myRef.current.scrollToIndex(...);
    }
}

代码语言:javascript
复制
if ((this.myRef !== null) && (this.myRef.current !== null)) {
    if (typeof this.myRef.current.scrollToIndex === "function") {
        try {
            this.myRef.current.scrollToIndex(...);
        } catch (error) {
            console.warn("Something went wrong", error);
        }
    }
}

我希望这对其他学习使用参考文献的人有帮助。干杯:)

票数 5
EN

Stack Overflow用户

发布于 2019-12-13 06:56:46

与Animated.ScrollView

  • 为您的FlatList创建一个ref (旧的只工作方式):

<ScrollView ref={ (ref) => (this.MyRef=ref) } />

使用this.myRef.getNode().scrollToIndex

  • Access scrollToIndex

不幸的是,Animated.FlatList目前没有工作.

与FlatList

  • 为您的FlatList创建一个参考:

<FlatList ref={ this.flatListRef } />

代码语言:javascript
复制
  constructor(props) {
    super(props);

    this.flatListRef = React.createRef();
  }

使用this.flatListRef.current.scrollToIndex

  • Access scrollToIndex

还要确保将代码包装在if语句中,如下所示:

代码语言:javascript
复制
 if (this.myRef.getNode()) { this.flatListRef.getNode().scrollToIndex(); }
票数 1
EN

Stack Overflow用户

发布于 2019-12-13 14:17:07

不知道这是否对你有帮助..。它滚动到列表中的特定项目:

代码语言:javascript
复制
/*Example to Scroll to a specific position in scrollview*/
import React, { Component } from 'react';
//import react in our project

import {
  View,
  ScrollView,
  StyleSheet,
  Text,
  TouchableOpacity,
  Image,
  TextInput,
} from 'react-native';
//import all the components we needed

export default class App extends Component {
  constructor() {
    super();
    //Array of Item to add in Scrollview
    this.items = [
      'zero',
      'one',
      'two',
      'three',
      'four',
      'five',
      'six',
      'seven',
      'eight',
      'nine',
      'ten ',
      'eleven',
      'twelve',
      'thirteen',
      'fourteen',
      'fifteen',
      'sixteen',
      'seventeen',
      'eighteen',
      'nineteen',
      'twenty ',
      'twenty-one',
      'twenty-two',
      'twenty-three',
      'twenty-four',
      'twenty-five',
      'twenty-six',
      'twenty-seven',
      'twenty-eight',
      'twenty-nine',
      'thirty',
      'thirty-one',
      'thirty-two',
      'thirty-three',
      'thirty-four',
      'thirty-five',
      'thirty-six',
      'thirty-seven',
      'thirty-eight',
      'thirty-nine',
      'forty',
    ];
    //Blank array to store the location of each item
    this.arr = [];
    this.state = { dynamicIndex: 0 };
  }
  downButtonHandler = () => {
    if (this.arr.length >= this.state.dynamicIndex) {
      // To Scroll to the index 5 element
      this.scrollview_ref.scrollTo({
        x: 0,
        y: this.arr[this.state.dynamicIndex],
        animated: true,
      });
    } else {
      alert('Out of Max Index');
    }
  };
  render() {
    return (
      <View style={styles.container}>
        <View
          style={{
            flexDirection: 'row',
            backgroundColor: '#1e73be',
            padding: 5,
          }}>
          <TextInput
            value={String(this.state.dynamicIndex)}
            numericvalue
            keyboardType={'numeric'}
            onChangeText={dynamicIndex => this.setState({ dynamicIndex })}
            placeholder={'Enter the index to scroll'}
            style={{ flex: 1, backgroundColor: 'white', padding: 10 }}
          />
          <TouchableOpacity
            activeOpacity={0.5}
            onPress={this.downButtonHandler}
            style={{ padding: 15, backgroundColor: '#f4801e' }}>
            <Text style={{ color: '#fff' }}>Go to Index</Text>
          </TouchableOpacity>
        </View>
        <ScrollView
          ref={ref => {
            this.scrollview_ref = ref;
          }}>
          {/*Loop of JS which is like foreach loop*/}
          {this.items.map((item, key) => (
            //key is the index of the array
            //item is the single item of the array
            <View
              key={key}
              style={styles.item}
              onLayout={event => {
                const layout = event.nativeEvent.layout;
                this.arr[key] = layout.y;
                console.log('height:', layout.height);
                console.log('width:', layout.width);
                console.log('x:', layout.x);
                console.log('y:', layout.y);
              }}>
              <Text style={styles.text}>
                {key}. {item}
              </Text>
              <View style={styles.separator} />
            </View>
          ))}
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 30,
  },
  separator: {
    height: 1,
    backgroundColor: '#707080',
    width: '100%',
  },

  text: {
    fontSize: 16,
    color: '#606070',
    padding: 10,
  },
});

如果我完全错了,告诉我.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59317474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档