Обновление ReactNative IOS Firebase MapStateToProps Обновление Проблема - PullRequest
1 голос
/ 10 октября 2019

У меня очень странная проблема, когда я даже не знаю, с чего начать отладку, поскольку это происходит только тогда, когда я запускаю приложение в тестовый полет. В основном я пытаюсь загрузить каналы на основе геолокации. Некоторые загружаются автоматически, а затем загружаются, если они находятся менее чем в 100 милях от горы (давайте назовем эти ОБЩЕСТВЕННЫЕ и ЧАСТНЫЕ каналы - оба из них находятся в одном списке). У меня есть эти 2 вызова Firebase в моем создателе действий и помещаю их в массив, а затем вызываю dispatch после. У меня есть проблема с FlatList, где он загружает каналы PUBLIC и только когда я прокручиваю, делаю PRIVATE каналы. Я пробовал несколько вещей, в том числе наиболее распространенную из этой конкретной проблемы с github (обновление плоского списка) 'removeClippedSubviews = {false}', дополнительные данные, чистые компоненты и т. Д., Но ни одна из них не сработала.

Вместо этого я нашел способ обойти это (я знаю, что это не самое лучшее, но я просто хочу решение, которое пока работает), просто установив тайм-аут и дождавшись каналов перед отправкой действия:

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

К сожалению, сейчас наступает момент, когда возникает сумасшедшая проблема. По сути, это работает для отладки, выпуска / всего, что я пробовал с XCode, но когда оно попадает на мое устройство, метод рендеринга в основном находится наиндикатор загрузки, пока я не переключаю вкладки с реагирующей навигацией. Это не имеет смысла для меня, так как это происходит не всегда (возможно, 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>
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...