简体   繁体   中英

React-Native/Redux - Unable to fetch data before component mounts

I'm having issues with fetching data from my web-service and updating this.props before the component is rendered.

Homepage.js

import React, { Component } from 'react';
import {View, Text, StyleSheet, Image} from 'react-native';
import { Header, Footer , CarouselSlide} from './common';
import { connect } from 'react-redux';
import { getQuests} from '../actions';
import Carousel from 'react-native-snap-carousel';

const SLIDER_1_FIRST_ITEM = 1;

class HomePage extends Component {

  constructor (props) {
    super(props);
    this.state = {
      slider1ActiveSlide: SLIDER_1_FIRST_ITEM,
      slider1Ref: null
    };
  }
  componentWillMount() {
    this.props.getAllQuests();
  }

  _renderItemWithParallax({item, index}, parallaxProps) {
    return(
      <CarouselSlide 
        data={item}
        parallaxProps={parallaxProps}
      />
    );
  }

  render() {
    const {containerStyle, questHeaderStyle, questHeaderTextStyle} = styles;
    const {slider1ActiveSlide, slider1Ref} = this.state;

    return(
      <View style={containerStyle}>
        <Header />

        <View style={questHeaderStyle}>
          <Text style={questHeaderTextStyle}>Quests</Text>
        </View>

        <Carousel 
          ref={(c) => { if (!this.state.slider1Ref) { this.setState({ slider1Ref: c}); } }}
          data={this.props.questObject}
          renderItem={this._renderItemWithParallax}
          sliderWidth={300}
          itemWidth={300}  
          hasParallaxImages={true}
          firstItem={1}
          inactiveSlideScale={0.94}
          inactiveSlideOpacity={0.7}
          enableMomentum={false}
          loop={true}
          loopClonesPerSide={2}
          autoplay={true}
          autoplayDelay={500}
          autoplayInterval={3000}
          onSnapToItem={(index) => this.setState({ slider1ActiveSlide: index})}
        />

        <Footer />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  containerStyle: {
    flex: 1
  },
  questHeaderStyle: {
    left: 17.5,
    top: 5
  },
  questHeaderTextStyle: {
    color: '#EF6D69',
    fontSize: 17.5,
    fontWeight: '800'
  }
})

const mapStateToProps = ({quest}) => {
  const { error, loading, questObject } = quest;

  return { error, loading, questObject};
};

const mapDispatchToProps = (dispatch) => {
  return {
    getAllQuests: () => {
      dispatch(getQuests());
    }
  };
};

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

it seems to only dispatch the action after the component has rendered, how do I dispatch the action before the component is mounted?

Since you are fetching the data from a web-service, it can take an unknown amount of time and you can't hold the rendering of the component till that time. What you need here is to maintain a state which tells if the quests has been retrieved from the server. If not, then you render a message saying Fetching quests or something and once you have some quests to render, you start rendering those. Pseudocode would like something like

class HomePage extends Component {
  state = {
    hasSomeQuests: false
  }

  updateHasSomeQuestsToRender = (newValue) => {
    this.setState({
      hasSomeQuests: newValue
    })
  }

  render() {
    if(!this.state.hasSomeQuests) {
      return <Fetching quests>
    }

    return JSX with the quests
  }
}

You update the hasSomeQuests state when you retrieve the quests and have at least one that you can render on the screen.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM