Anu
Anu

Reputation: 1742

How to delay rendering of components on fetch request in react native?

While fetching request how do I put rendering on hold?Because in my code I'm fetching request server on button click and also I'm rendering the fetched response after that.But rendering occurs before fetching so I'm getting undefined value when I mapped over the responseData within render.Following is my code

updated

screen.js

import { article } from "./data";
import PopupDialog from "react-native-popup-dialog";
import AddNewarticle from "./AddNewarticle";

class SecondScreen extends Component {
  state = { res: [] };
  constructor() {
    super();

    this.initialState = {
      modalVisible: false,
      Disable_Button: false,
      ViewArray: []
    };
    this.state = this.initialState;
    this.animatedValue = new Animated.Value(0);
    this.Array_Value_Index = 0;
  }
  Add_New_View_Function = () => {
    this.animatedValue.setValue(0);

    let New_Added_View_Value = { Array_Value_Index: this.Array_Value_Index };

    this.setState(
      {
        Disable_Button: true,
        ViewArray: [...this.state.ViewArray, New_Added_View_Value]
      },
      () => {
        Animated.timing(this.animatedValue, {
          toValue: 1,
          duration: 400,
          useNativeDriver: true
        }).start(() => {
          this.Array_Value_Index = this.Array_Value_Index + 1;

          this.setState({ Disable_Button: false });
        });
      }
    );
  };

  onPressButton() {
    onPressSubmit();
    Add_New_View_Function();
  }
  onPressSubmit() {
    fetch("xxxxx", {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        url: this.state.url
      })
    })
      .then(response => response.json())
      .then(responseData => {
        this.setState({
          res: responseData,
          loaded: true
        });
      })
      .catch(() => {
        this.setState({ showLoading: true });
      });
  }

  render() {
    const AnimationValue = this.animatedValue.interpolate({
      inputRange: [0, 1],

      outputRange: [-59, 0]
    });
    let Render_Animated_View = this.state.ViewArray.map((item, key) => {
      if (key == this.Array_Value_Index) {
        return (
          <Animated.View
            key={key}
            style={[
              styles.Animated_View_Style,
              {
                opacity: this.animatedValue,
                transform: [{ translateY: AnimationValue }]
              }
            ]}
          >
            <Text />
          </Animated.View>
        );
      } else {
        return (
          <View key={key} style={styles.Animated_View_Style}>
            {this.state.res.map(a => (
              <TouchableOpacity onPress={() => console.log("clicked")}>
                <CardSection>
                  <View style={{ flexDirection: "row" }}>
                    <Text style={styles.textStyle}>{a.title}</Text>
                  </View>
                </CardSection>
              </TouchableOpacity>
            ))}
          </View>
        );
      }
    });
    return (
      <View style={styles.MainContainer}>
        <ScrollView>
          <View style={{ flex: 1, padding: 2 }}>{Render_Animated_View}</View>
        </ScrollView>

        <TouchableOpacity
          activeOpacity={0.7}
          style={styles.TouchableOpacityStyle}
          disabled={this.state.Disable_Button}
          onPress={() => this.popupDialog.show()}
        >
          <Image
            source={{
              uri:
                "https://reactnativecode.com/wp-content/uploads/2017/11/Floating_Button.png"
            }}
            style={styles.FloatingButtonStyle}
          />
        </TouchableOpacity>
        <PopupDialog
          ref={popupDialog => {
            this.popupDialog = popupDialog;
          }}
          dialogStyle={{ backgroundColor: "#f2ddd5", height: 100 }}
          containerStyle={{ zIndex: 50, elevation: 100 }}
          overlayBackgroundColor="#000"
          dismissOnTouchOutside={true}
        >
          <View>
            <TextInput
              style={{ height: 40 }}
              placeholder="Enter the url you want to save!"
              multiline
              onChangeText={url => this.setState({ url })}
              underlayColor="#fcc9b5"
            />

            <Button title="Ok" onPress={() => this.onPressButton.bind(this)} />
          </View>
        </PopupDialog>
      </View>
    );
  }
}
export default SecondScreen;

updated

Currently I'm fetching article (json data containing a list of articles) and rendering some cards with the fetch response i.e, title is displayed within cards.At the end of it there will be an add button on clicking that button a popup will be displayed, within that there will be field to paste article's link and by clicking on tick icon it will be send to server , and I will get a json response back (res). So I want the data within this res to be rendered and show card list with the data within res. How can this be done?For now I've tried several methods.So there will 2 rendering where do I call this renderArticle?Please help..Hope you understand what I'm saying..Any queries please feel free to ask..

Upvotes: 0

Views: 2020

Answers (3)

Mohammed Ashfaq
Mohammed Ashfaq

Reputation: 3426

IF res is an array of objects

// res = [{title:'article1'},{title:'article2'}] ] 

renderArticle(){
  if(this.state.res.length){
    return this.state.res.map(newarticle =>
      // Your code
    )
  }else {
    return null
  }
}

IF res is in below form

res = {
  article1Detail: {title:'article1'}, 
  article2Detail: {title:'article2'} 
}


renderArticle(){
  if(Object.values(this.state.res).length){
    return Object.values(this.state.res).map(newarticle =>
      // Your code
    )
  }else {
    return null
  }
}

Upvotes: 1

Callcter
Callcter

Reputation: 1

give res a init value like [] or judge res is undefined in your render function

Upvotes: 0

Harkirat Saluja
Harkirat Saluja

Reputation: 8114

import { article } from "./data";
......
.....
onPressSubmit() {
     this.setState({ showLoading: true});
    fetch( // api info})
    .then((response) => response.json())
    .then((responseData) => {
        this.setState({
            showLoading: false,
            res:responseData
        })
     })
    .catch(() => {
      this.setState({showLoading: false});
    })
  }

render() {
  return () {
    if (this.state.showLoading) {
      // return spinner
    }

    return this.renderArticle();
  }
}

  renderArticle(){

    /**
    check if state has data then 
    render content or render null 
    (can happen when api fails)
    **/
  }

Upvotes: 0

Related Questions