当页面以React-native呈现时,如何显示加载程序图标?

时间:2019-09-01 11:33:48

标签: react-native rendering react-navigation

我实际上是在react-native应用程序中渲染Complex UI。我正在使用反应导航。每当我单击导航抽屉中用于我的复杂UI页面的选项时,整个应用程序将挂起3-5秒,然后显示该页面。我想要的是一个加载器屏幕,当我单击导航抽屉中的选项时,加载器屏幕将立即加载,并且当呈现复杂的UI时,加载器应消失并显示UI。由于呈现UI,应用程序冻结。显示加载屏幕后,有什么方法可以异步呈现UI?

编辑

下面是我前面提到的复杂UI。当我导航到此页面时,将加载该表。

// source https://snack.expo.io/@shrey/highly-responsive-sheet
import React from "react"
import { Animated, ActivityIndicator, FlatList, ScrollView, StyleSheet, Text, View,TouchableOpacity } from "react-native"

const NUM_COLS = 15
const NUM_ROWS_STEP = 20
const CELL_WIDTH = 100
const CELL_HEIGHT = 60

const black = "#000"
const white = "#fff"

const styles = StyleSheet.create({
  container: { backgroundColor: white, marginVertical: 40, marginBottom: 80 },
  header: { flexDirection: "row", borderTopWidth: 1, borderColor: black },
  identity: { position: "absolute", width: CELL_WIDTH },
  body: { marginLeft: CELL_WIDTH },
  cell: {
    width: CELL_WIDTH,
    height: CELL_HEIGHT,
    borderRightWidth: 1,
    borderBottomWidth: 1,
    borderColor: black,
  },
  column: { flexDirection: "column" },
})

class Sheet extends React.Component {
  constructor(props: {}) {
    super(props)

    this.headerScrollView = null
    this.scrollPosition = new Animated.Value(0)
    this.scrollEvent = Animated.event(
      [{ nativeEvent: { contentOffset: { x: this.scrollPosition } } }],
      { useNativeDriver: false },
    )

    this.state = { count: NUM_ROWS_STEP, loading: false }
  }

  handleScroll = e => {
    if (this.headerScrollView) {
      let scrollX = e.nativeEvent.contentOffset.x
      this.headerScrollView.scrollTo({ x: scrollX, animated: false })
    }
  }

  scrollLoad = () => this.setState({ loading: false, count: this.state.count + NUM_ROWS_STEP })

  handleScrollEndReached = () => {
    if (!this.state.loading) {
      this.setState({ loading: true }, () => setTimeout(this.scrollLoad, 500))
    }
  }

  formatCell(value) {
    return (
     <TouchableOpacity onPress=()>
      <View key={value} style={styles.cell}>
        <Text>{value}</Text>
      </View>
    </TouchableOpacity>
    )
  }

  formatColumn = (section) => {
    let { item } = section
    let cells = []

    for (let i = 0; i < this.state.count; i++) {
      cells.push(this.formatCell(`col-${i}-${item.key}`))
    }

    return <View style={styles.column}>{cells}</View>
  }

  formatHeader() {
    let cols = []
    for (let i = 0; i < NUM_COLS; i++) {
      cols.push(this.formatCell(`frozen-row-${i}`))
    }

    return (
      <View style={styles.header}>
        {this.formatCell("frozen-row")}
        <ScrollView
          ref={ref => (this.headerScrollView = ref)}
          horizontal={true}
          scrollEnabled={false}
          scrollEventThrottle={16}
        >
          {cols}
        </ScrollView>
      </View>
    )
  }

  formatIdentityColumn() {
    let cells = []
    for (let i = 0; i < this.state.count; i++) {
      cells.push(this.formatCell(`frozen-col-${i}`))
    }

    return <View style={styles.identity}>{cells}</View>
  }

  formatBody() {
    let data = []
    for (let i = 0; i < NUM_COLS; i++) {
      data.push({ key: `content-${i}`})
    }

    return (
      <View>
        {this.formatIdentityColumn()}
        <FlatList
          style={styles.body}
          horizontal={true}
          data={data}
          renderItem={this.formatColumn}
          stickyHeaderIndices={[0]}
          onScroll={this.scrollEvent}
          scrollEventThrottle={16}
          extraData={this.state}
        />
      </View>
    )
  }

  formatRowForSheet = (section) => {
    let { item } = section

    return item.render
  }

  componentDidMount() {
    this.listener = this.scrollPosition.addListener(position => {
      this.headerScrollView.scrollTo({ x: position.value, animated: false })
    })
  }

  render () {
    let body = this.formatBody()

    let data = [{ key: "body", render: body }]

    return (
      <View style={styles.container}>
        {this.formatHeader()}
        <FlatList
          data={data}
          renderItem={this.formatRowForSheet}
          onEndReached={this.handleScrollEndReached}
          onEndReachedThreshold={.005}
        />
        {this.state.loading && <ActivityIndicator />}
      </View>
    )
  }
}

export default Sheet

2 个答案:

答案 0 :(得分:1)

您的UI可能也加载缓慢,因为您正在FlatList中使用FlatList。以我的经验,这只会引起混乱和性能问题。

您可能还想做的一件事就是与Redux之类的东西集成,以处理全局加载状态,并根据该值显示一个加载微调器或数据。

答案 1 :(得分:0)

没有看到实际的代码,我只能提出高级解决方案:

  1. 考虑使用requestAnimationFrameInteractionManager安排昂贵的计算。
  2. 首先呈现加载状态,然后收听导航焦点事件以开始呈现您的Complex UI。
  3. 请记住要在生产模式下进行测试,因为与开发的区别可能很明显。

链接到我提到的概念:

  1. https://facebook.github.io/react-native/docs/performance#my-touchablex-view-isn-t-very-responsive
  2. https://facebook.github.io/react-native/docs/timers#interactionmanager
  3. https://reactnavigation.org/docs/en/navigation-events.html