ReactNative IOS Testflight Firebase MapStateToProps更新问题

时间:2019-10-10 04:18:18

标签: ios firebase react-native promise testflight

我遇到了一个非常奇怪的问题,我什至不知道从哪里开始调试,因为它只有在我将应用程序投入试飞时才会发生。基本上,我正在尝试根据地理位置加载频道。一些自动加载,如果距离山顶不到100英里,则某些会自动加载(让我们将它们称为PUBLIC和PRIVATE通道,它们都在同一列表中)。我在动作创建器中有这两个firebase调用,并将它们推送到数组中,然后再调用dispatch。我在FlatList上有一个问题,它在其中加载PUBLIC通道,并且只有在滚动时才对PRIVATE通道进行操作。我尝试了很多方法,包括该特定github问题(更新列表)中的最常见问题(“ removeClippedSubviews = {false}”),额外的数据,纯组件等,但均无用。

相反,我找到了解决此问题的方法(我知道这不是最好的方法,但是我只想要一种目前可行的解决方案),方法是设置超时时间并在调度操作之前等待频道:

setTimeout(function(){ dispatch(loadPublicChannelsSuccess(data)); }, 10);

不幸的是,现在是疯狂的问题出现了。基本上,它适用于调试,发布/我使用XCode尝试过的所有方法,但是当它进入我的设备时,render方法基本上位于加载指示器,直到我切换选项卡与反应导航。这对我来说是没有意义的,因为这种情况并非总是(可能是80%)发生在时间上,而且仅在迄今为止的试飞中才发生。在设置超时之前,我从未见过这个,所以也不确定是否从哪里开始:

render() {
    const {loadPublicChannels, loading, publicChannels, checkedInMountain, selectedMountain} = this.props;
    return !loadPublicChannels && publicChannels && !loading 
    ? (
      <MessagePanelPublic publicChannels={publicChannels} selectedMountain={selectedMountain}/>
    ) : (
      <LoadingAnimation />
    );
  }

动作

export const getUserPublicChannels = () => {
  return (dispatch, state) => {
    dispatch(loadPublicChannels());
    // get all mountains within distance specified
    let mountainsInRange = state().session.mountainsInRange;
    // get the user selected mountain
    let selectedMountain = state().session.selectedMountain;

    // see if the selected mountain is in range to add on additional channels
    let currentMountain;
    mountainsInRange
      ? (currentMountain =
          mountainsInRange.filter(mountain => mountain.id === selectedMountain)
            .length === 1
            ? true
            : false)
      : (currentMountain = false);

    // mountain public channels (don't need to be within distance)
    let currentMountainPublicChannelsRef = FIREBASE_REF_CHANNEL_INFO.child(
      "Public"
    )
      .child(`${selectedMountain}`)
      .child("Public");

    // mountain private channels- only can see if within range (geolocation)
    let currentMountainPrivateChannelsRef = FIREBASE_REF_CHANNEL_INFO.child(
      "Public"
    )
      .child(`${selectedMountain}`)
      .child("Private");

    // get public channels
    return currentMountainPublicChannelsRef
      .orderByChild("key")
      .once("value")
      .then(snapshot => {
        let publicChannelsToDownload = [];
        snapshot.forEach(channelSnapshot => {
          let channelId = channelSnapshot.key;
          let channelInfo = channelSnapshot.val();
          // add the channel ID to the download list
          publicChannelsToDownload.push({ id: channelId, info: channelInfo });
        });

        // if mountain exists then get private channels/ if in range
        if (currentMountain) {
          currentMountainPrivateChannelsRef
            .orderByChild("key")
            .once("value")
            .then(snapshot => {
              snapshot.forEach(channelSnapshot => {
                let channelId = channelSnapshot.key;
                let channelInfo = channelSnapshot.val();
                publicChannelsToDownload.push({
                  id: channelId,
                  info: channelInfo
                });
              });
            });
        }
        return publicChannelsToDownload;
      })

      .then(data => {
        setTimeout(function(){ dispatch(loadPublicChannelsSuccess(data)); }, 10);

      });
  };
};

与公共频道有关的减速器

case types.LOAD_PUBLIC_CHANNELS:
  return {
    ...state,
    loadPublicChannels: true
  };

case types.LOAD_PUBLIC_CHANNELS_SUCCESS:
  console.log("PUBLIC");
  console.log(action.publicChannels);
  console.log(action);
  return {
    ...state,
    publicChannels: action.publicChannels,
    loadPublicChannels: false,
    messages: {}
  };

case types.LOAD_PUBLIC_CHANNELS_ERROR:
  return {
    ...state,
    channelsPublicError: action.error,
    loadPublicChannels: false
  };

调用mapStateToProps和mapDispatchToProps的容器

class MessagePanelPublicContainer extends Component {
  constructor(props) {
    super(props);
  }

  // get public and private channels from redux
  async componentDidMount() {
    this.props.getUserPrivateChannels();
    this.props.loadCurrentUser();
    // this.props.getUserPublicChannels();
  }

  componentDidUpdate(prevProps) {
    if (this.props.mountainsInRange && prevProps.mountainsInRange !== this.props.mountainsInRange || prevProps.selectedMountain !== this.props.selectedMountain) {
      this.props.getUserPublicChannels();
    }
  }

  lessThan12HourAgo = (date) => {
    return moment(date).isAfter(moment().subtract(12, 'hours'));
  }

  render() {
    const {loadPublicChannels, loading, publicChannels, checkedInMountain, selectedMountain} = this.props;
    return !loadPublicChannels && publicChannels && !loading 
    ? (
      <MessagePanelPublic publicChannels={publicChannels} selectedMountain={selectedMountain}/>
    ) : (
      <LoadingAnimation />
    );
  }
}

const mapStateToProps = state => {
return {
  publicChannels: state.chat.publicChannels,
  loadPublicChannels: state.chat.loadPublicChannels,
  currentUser: state.chat.currentUser,
  loading: state.chat.loadCurrentUser,
  mountainsInRange: state.session.mountainsInRange,
  selectedMountain: state.session.selectedMountain,
};
}

const mapDispatchToProps = {
  loadCurrentUser,
  getUserPublicChannels,
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(MessagePanelPublicContainer);

组件

import React, { Component } from "react";
import { View, Text, FlatList, ImageComponent } from "react-native";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { ListItem, Icon, Button } from "react-native-elements";
import { withNavigation } from "react-navigation";
import LinearGradient from "react-native-linear-gradient";
import styles from "./Styles";
import moment from 'moment';
import FastImage from 'react-native-fast-image';
class MessagePanelPublicComponent extends Component {

  render() {
    // rendering all public channels
    const renderPublicChannels = ({ item }) => {
      return (
        <ListItem
          leftAvatar={{
            source: { uri: item.info.ChannelPicture },
            rounded: false,
            overlayContainerStyle: { backgroundColor: "white" },
            ImageComponent: FastImage
          }}
          title={item.info.Name}
          titleStyle={styles.title}
          chevron={true}
          bottomDivider={true}
          id={item.Name}
          containerStyle={styles.listItemStyle}
        />
      );
    };

    const renderText = () => {
      return (
        <View style={styles.extraTextContainer}>
          <Text style={styles.extraText}>
            Get within 100 miles from resort or select a closer resort to see more channels...
          </Text>
          <Icon
            name="map-marker"
            type="font-awesome"
            size={40}
            iconStyle={styles.extraIcon}
          />
        </View>
      );
    };


    return (
      <View style={styles.container}>
        <View style={styles.channelList}>
          <FlatList
            data={this.props.publicChannels}
            renderItem={renderPublicChannels}
            // keyExtractor={item => item.Name}
            keyExtractor={(item, index) => index.toString()}
            extraData={this.props.publicChannels}
            removeClippedSubviews={false}
          />
          {this.props.publicChannels.length < 3 ? renderText() : null}
        </View>
      </View>
    );
  }
}

0 个答案:

没有答案