React Native - 在this.intervalHandle = setInterval中更新道具时,屏幕闪烁

时间:2018-01-25 18:08:37

标签: ios reactjs react-native redux

我的问题是我想要更新我的数据并在屏幕上实时显示,但每次我尝试更新this.props.stoveUsage时,我在此处进行this.getUsage()调用时,我的屏幕变为空白。 intervalHandle = setInverval

这是我的问题所在:

  componentDidMount () {
    console.log('Enter StatsScreen.componentDidMount')
    this.drawer.drawer.setNativeProps({ style: { width: 0 } })
    this.intervalHandle = setInterval(() => {
      this.getUsage()
    }, 30000)
  }

this.getUsage应该更新getStoveUsage中的道具:(deviceId,viewType,start)=> dispatch(SmarturnsActions.getUsage(deviceId,viewType,start))

const mapDispatchToProps = (dispatch) => {
  return {
    selectDevice: (selectedDeviceId) => 
dispatch(SmarturnsActions.deviceSelected(selectedDeviceId)),
    getStoveUsage: (deviceId, viewType, start) => 
dispatch(SmarturnsActions.getUsage(deviceId, viewType, start))
  }
}

完整代码:

class Stats extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      viewType: 'day',
      dt: moment(),
      device: {},
      updateFlipFlop: true
    }

    this.intervalHandle = null
  }

  static navigationOptions = {
    tabBarLabel: I18n.t('$tab_usage'),
    tabBarIcon: ({ tintColor, focused }) => {
      return (
        <Image
          source={focused ? Images.tabStatsActive : Images.tabStats}
          style={[styles.tabIcon, { tintColor: tintColor }]}
        />
      )
    }
  }

  getDevice = (selectedDeviceId) => {
    const devices = this.props.devices || []
    let dev = {}

    devices.forEach((d) => {
      if (d._id === selectedDeviceId) {
        dev = d
      }
    })
    if (!dev._id && devices.length) {
      dev = devices[0]// dev is the device we are working with
    }
    this.setState({ device: dev }, () => {
      this.getUsage()
    })
  }

  componentDidMount () {
    console.log('Enter StatsScreen.componentDidMount')
    this.drawer.drawer.setNativeProps({ style: { width: 0 } })
    this.intervalHandle = setInterval(() => {
      this.getUsage()
    }, 30000)
  }
  componentWillMount () {
    console.log('Enter StatsScreen.componentWillMount')
    this.getDevice(this.props.selectedDeviceId)
  }

  componentWillUnmount = () => {
    console.log('Enter MainScreen.componentWillUnmount()')
    if (this.intervalHandle) clearInterval(this.intervalHandle)
  }

  componentWillReceiveProps (nextProps) {
    if (nextProps.selectedDeviceId !== this.props.selectedDeviceId) {
      this.getDevice(nextProps.selectedDeviceId)
    } else if (nextProps.stoveUsage !== this.props.stoveUsage) {
      this.setState({ updateFlipflop: !this.state.updateFlipflop })
    }
  }

  onPressPrev = () => {
    console.log('onPressPrev')
    console.log('state=', this.state)
    const dt = moment(this.state.dt).add(-1, this.state.viewType + 's')     // converts to 'days', 'weeks', 'months'
    this.setState({ dt }, () => {
      this.getUsage()
    })
  }

  onPressNext = () => {
    console.log('onPressNext')
    const dt = moment(this.state.dt).add(1, this.state.viewType + 's') // converts to 'days', 'weeks', 'months'
    this.setState({ dt }, () => {
      this.getUsage()
    })
  }

  onPressCalendar = () => {
    console.log('onPressCalendar')
  }

  getUsage = () => {
    let dt = this.state.dt
    let vt = this.state.viewType
    let dev = this.state.device
    let date
    if (vt === 'day') {
      date = moment(dt).format('YYYY-MM-D')
    } else if (vt === 'week') {
      date = moment(dt).startOf('week').format('YYYY-MM-D')
    } else {
      date = moment(dt).format('YYYY-MM')
    }
    this.props.getStoveUsage(dev._id, vt, date)
  }

  onPressSegment = (viewType) => {
    console.log('click on segment ', viewType)
    this.setState({ viewType: viewType, dt: moment() }, () => {
      this.getUsage()
    })
  }

  _onStovePress = (stove) => {
    console.log('Enter StatsScreen._onStovePress. stove=', stove._id)
    this.props.selectDevice(stove._id)
    this.closeDrawer()
  }

  formatDate = (dt) => {
    if (this.state.viewType === 'day') {
      return moment(dt).calendar(null, {
        sameDay: '[Today]',
        nextDay: '[Tomorrow]',
        lastDay: '[Yesterday]',
        lastWeek: 'ddd, MMM D',
        sameElse: 'ddd, MMM D'
      })
    } else if (this.state.viewType === 'week') {
      return moment(dt).startOf('week').format('MMM D') + ' - ' + moment(dt).startOf('week').add(6, 'days').format('MMM D')
    } else {
      return moment(dt).format('MMM, YYYY')
    }
  }

  displayUsage = () => {
    if (!this.props.fetching && this.props.stoveUsage) {
      const total = moment.duration(this.props.stoveUsage.total, 'seconds').format('H:mm', {trim: false})
      const average = this.props.stoveUsage.average
      const usage = this.props.stoveUsage.usage
      if (this.state.viewType === 'day') {
        return <UsageDay totalUsage={total} average={average} usage={usage} date={this.state.dt} />
      } else if (this.state.viewType === 'week') {
        return <UsageWeek totalUsage={total} usage={usage} />
      } else {
        return <UsageMonth totalUsage={total} usage={usage} />
      }
    }
  }

  closeDrawer = () => {
    this.drawer.close()
    this.drawer.drawer.setNativeProps({ style: { width: 0 } })
  }
  openDrawer = () => {
    this.drawer.drawer.setNativeProps({ style: { width: this.drawer.getDrawerWidth() } })
    this.drawer.open()
  }

  _renderDrawer = (dev) => {
    const allStoves = this.props.devices || []
    const devices = allStoves.filter((d) => { return d.follower.enabled     })

    const selfStoves = devices.filter(d => !d.is_shared)
    const sharedStove = devices.filter(d => !!d.is_shared)

    return (
      <ScrollView style={[styles.drawerContainer]}>
        <View style={styles.drawerHeader} >
          <Text style={{ color: '#fff' }}>{dev.owner_username}</Text>
        </View>

        <List>
          <ListItem itemDivider>
            <Text>{I18n.t('$setting_my_smarturns')}</Text>
          </ListItem>
          {
            selfStoves.map(stove => (
              <ListItem key={stove._id}
                onPress={() => { this._onStovePress(stove) }} >
                <Body>
                  <Text>{stove.name}</Text>
                  <Text note>{stove.owner_username}</Text>
                </Body>
              </ListItem>
            ))
          }

          <ListItem itemDivider>
            <Text>{I18n.t('$setting_others_smarturns')}</Text>
          </ListItem>
          {
            sharedStove.map(stove => (
              <ListItem key={stove._id}
                onPress={() => { this._onStovePress(stove) }} >
                <Body>
                  <Text>{stove.name}</Text>
                  <Text note>{stove.owner_username}</Text>
                </Body>
              </ListItem>
            ))
          }
        </List>
      </ScrollView>)
  }

  render () {
    console.log('Enter StatsScreen.render()')

    let dt = this.state.dt

    if (this.state.viewType === 'week') dt = moment(dt).startOf('week')

    const dateStr = this.formatDate(dt)

    return (

      <StyleProvider style={getTheme(commonColor)}>
        <Container>
          <Drawer ref={(ref) => { this.drawer = ref }}
            type='overlay'
            tapToClose
            openDrawerOffset={0.3}
            content={this._renderDrawer(this.state.device)}
            onClose={() => this.closeDrawer()} >
            <Header hasSubtitle>
              <Left>
                <Button transparent onPress={this.openDrawer}>
                  <Icon name='navicon' />
                </Button>
              </Left>
              <Body >
                <Title>{I18n.t('$usage_title')}</Title>
                <Subtitle style={{ color: 'white' }} ellipsizeMode='tail' numberOfLines={1}>{this.state.device.name}</Subtitle>
              </Body>
              <Right />
            </Header>
            <Segment>
              <Button first active={this.state.viewType === 'day'} onPress={() => this.onPressSegment('day')}><Text>Daily</Text></Button>
              <Button active={this.state.viewType === 'week'} onPress={() => this.onPressSegment('week')}><Text>Weekly</Text></Button>
              <Button last active={this.state.viewType === 'month'} onPress={() => this.onPressSegment('month')}><Text>Monthly</Text></Button>
            </Segment>
            <View style={{ flexDirection: 'row', justifyContent: 'space-between', height: 40 }}>
              <View>
                <Button transparent onPress={this.onPressPrev}>
                  <Icon name='angle-left' style={{ color: 'rgba(46, 88, 137, 1)' }} />
                </Button>
              </View>
              <View>
                <Button transparent onPress={this.onPressCalendar}>
                  <Text note>{dateStr}</Text>
                  {/* <Icon name='calendar' /> */}
                </Button>
              </View>
              <View>
                <Right>
                  <Button transparent onPress={this.onPressNext}>
                    <Icon name='angle-right' style={{ color: 'rgba(46, 88, 137, 1)' }} />
                  </Button>
                </Right>
              </View>
            </View>

            <Content contentContainerStyle={{ flex: 1 }}>
              {this.displayUsage()}
            </Content>
          </Drawer>
        </Container>

      </StyleProvider>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    fetching: state.smarturns.fetching,
    devices: state.smarturns.devices,
    selectedDeviceId: state.smarturns.selectedDeviceId,
    stoveUsage: state.smarturns.usage
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    selectDevice: (selectedDeviceId) => dispatch(SmarturnsActions.deviceSelected(selectedDeviceId)),
    getStoveUsage: (deviceId, viewType, start) => dispatch(SmarturnsActions.getUsage(deviceId, viewType, start))
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Stats)

0 个答案:

没有答案