1

UPDATED CODE

  • This now fetches the data when button clicked but I cant display it as it did when it loaded first time?

I am totally new with react native so I am sorry if I explain my problem wrong or seem a little thick. I have made a screen that fetches data and displays the data and it seems to work quite well. However I have a couple of buttons and I want to add an onclick to call a function.

Maybe I am getting this wrong but its supposed to work like javascript which I have no problem with but I think I am missing something with the difference between components and functions.

For example in my code its just automatically fetches the data and displays it. How would I make functions to load the data when one the buttons is clicked and also update the view with the new loaded data?

I have tried putting the functions in with the fetch data but I seem to have to add everything but surely I can make re-usable functions for each task like I would in javascript.

I have included my code for the page and also what I have tried. Any help of advice would be great as when I am researching on the net I get confused information between reactjs and native.

Also all the code below has been snippets taken from various places and played around with so it is totally probably all wrong in terms of structure.

The code :

import React from "react";
import {
StyleSheet,
View,
ActivityIndicator,
FlatList,
Text,
StatusBar,
Image,
TouchableOpacity,
ScrollView,
SafeAreaView
} from "react-native";
import Icon from "react-native-vector-icons/Entypo";
import CupertinoButtonPurple1 from "../components/CupertinoButtonPurple1";
import Removebutton from "../components/removebutton";


export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: true,
dataSource:[] };
}
componentDidMount(){
fetch("https://www.uberfantasies.com/testv2.php")
.then(response => response.json())
.then((responseData)=> {
this.setState({
loading: false,
dataSource: responseData.data
})
})
.catch(error=>console.log(error)) //to catch the errors if any
}
FlatListItemSeparator = () => {
return (

<View/>
);
}
renderItem=(data)=>


<SafeAreaView>
 <View style={styles.container}>
      <View style={styles.rect}>
        <View style={styles.imageRow}>
          <Image source={{uri: data.item.image}} style={styles.image} />
          <View style={styles.group2Column}>
            <View style={styles.group2}>
              <Text style={styles.bitch}>
              <Text>{data.item.from} sent you a mesage!</Text>
              </Text>
              <Text style={styles.loremIpsum}>
                &quot;{data.item.message}&quot;
              </Text>
            </View>
            <View style={styles.loremIpsum2Row}>
              <Text style={styles.loremIpsum2}>{data.item.when}</Text>
              <View style={styles.loremIpsum2Filler}></View>
              <View style={styles.group3}>
                <CupertinoButtonPurple1
                  style={styles.cupertinoButtonPurple1}
                ></CupertinoButtonPurple1>
                <Removebutton
                  style={styles.removebutton}
                ></Removebutton>
              </View>
            </View>
          </View>
        </View>
      </View>
    </View>
</SafeAreaView>

render(){
if(this.state.loading){
return(
<View style={styles.loader}>
<ActivityIndicator size="large" color="#0c9"/>
</View>
)}
return(
<View style={styles.container}>

<FlatList
data= {this.state.dataSource}
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem= {item=> this.renderItem(item)}
keyExtractor= {item=>item.id.toString()}
/>

</View>
)}
}
const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  loader:{
  flex: 1,
  justifyContent: "center",
  alignItems: "center",
  backgroundColor: "#fff"
  },
  rect: {
    height: 97,
    backgroundColor: "rgba(230,230, 230,0.57)",
    borderWidth: 0,
    borderColor: "rgba(0,0,0,0.57)",
    marginTop: 0,
    borderBottomWidth: 1,
borderBottomColor: "#d5d5d5",
backgroundColor: "#f4f4f4"
  },
  image: {
    width: 80,
    height: 80,
        borderRadius: 15,
    borderWidth:  4,
    borderColor: '#ffffff',
    shadowColor: '#d5d5d5',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.8,
    shadowRadius: 2
  },
  group2: {
   
    height: 41
  },
  bitch: {
    fontFamily: "sans-serif-condensed",
    color: "#121212",
    fontSize: 14,
    height: 17,
    fontWeight: "bold",
    marginTop: 2
  },
  loremIpsum: {
    fontFamily: "sans-serif-condensed",
    color: "#121212",
    height: 17,
    width: 159,
    marginTop: 4
  },
  loremIpsum2: {
    fontFamily: "sans-serif-condensed",
    color: "#121212",
    fontSize: 10,
    marginTop: 8
  },
  loremIpsum2Filler: {
    flex: 1,
    flexDirection: "row"
  },
  group3: {
    width: 125,
    height: 26,
    
    flexDirection: "row",
    justifyContent: "space-between",
    marginRight: 25
  },
  cupertinoButtonPurple1: {
    height: 25,
    width: 57
  },
  cupertinoButtonDanger2: {
    height: 25,
    width: 57
  },
  loremIpsum2Row: {
    height: 26,
    flexDirection: "row",
    marginTop: 17,
    marginRight: 33,
    width: "100%"
  },
  group2Column: {
    width: 275,
    marginLeft: 16
  },
  imageRow: {
    height: 84,
    flexDirection: "row",
    marginTop: 8,
    marginLeft: 4
  }
});

and the way I have tried to make a function and the way I think it should work with results?

The UPDATED code that fetches data but I cant get it to display data how it did in the previous code? Going out my nut here because I think Im missing something silly. If I had only one element to display or change I could do it but I think its because it looks through the results? Am i wrong?

Heres the code:

import React, { useState, Component } from 'react'
import {
StyleSheet,
View,
ActivityIndicator,
FlatList,
Text,
StatusBar,
Image,
TouchableOpacity,
ScrollView,
SafeAreaView
} from 'react-native'
class App extends Component {
  state = {
    loading: true,
    dataSource:[],
    Status: "Not loaded"
  }

  onPress = () => {

fetch("https://www.uberfantasies.com/testv.php")
.then(response => response.json())
.then((responseData)=> {

this.setState({
loading: false,
Status: "Loaded",
dataSource: responseData.data
}) 

console.log(this.state.dataSource)
})

.catch(error=>console.log(error)) //to catch the errors if any

}

 render() {
   
    return (
      <View style={styles.container}>
        <TouchableOpacity
         style={styles.button}
         onPress={this.onPress}
        >
         <Text>Click me</Text>
        </TouchableOpacity>
        <View>
          <Text>
            Status : { this.state.Status }
          </Text>
        </View>
      </View>
    )
  }
}



const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  button: {
    alignItems: 'center',
    backgroundColor: '#DDDDDD',
    padding: 10,
    marginBottom: 10
  },
  loader:{
  flex: 1,
  justifyContent: "center",
  alignItems: "center",
  backgroundColor: "#fff"
  }
})

export default App;
JulesUK
  • 359
  • 2
  • 11
  • The following post has helpful answers [https://stackoverflow.com/questions/64648118/react-fetch-data-on-button-click](https://stackoverflow.com/questions/64648118/react-fetch-data-on-button-click) – w. Patrick Gale Apr 18 '22 at 19:25
  • Thats react not native isnt it? – JulesUK Apr 18 '22 at 19:30
  • 1
    For this is shouldn't matter. You need to remove the fetch from the componentDidMount (since that simply loads the data as soon as the component loads) and move it to your button event handler. – w. Patrick Gale Apr 18 '22 at 19:41

3 Answers3

0

if you want to call a function within onPress you need to call it. Like

<Button title="Press Me" onPress={() => ReloadData()} />
PlaeschZ
  • 41
  • 1
  • 6
  • It doesnt do anything, do I have to make it pressable and how do I split the functions as described above? Thanks – JulesUK Apr 18 '22 at 17:15
  • exact you need to do like this ... onPress={() => MyFunc()} otherwise it won't call that function – PlaeschZ Apr 18 '22 at 17:19
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – w. Patrick Gale Apr 18 '22 at 19:27
0

Below is a sample code snippet. I have used the function component as it is easy for a beginner. Assuming your output of the API call is a list, I am setting it to the state variable. SO whenever the 'apiData' variable value changes your component will re-render. You can user either a button or a touchable wrapper component for a clickable item.

const [apiData, setApiData] = useState([]);

const MySampleComponent = () => {
  const apiCall = () => {
    //Your code
     setApiData(result);

  };
  const renderListItem = (itemData) => <Text>{itemData.item.<your key>}</Text>;
  return (
    <View>
      <FlatList
        keyExtractor={item => item.id}
        data={apiData}
        renderItem={renderListItem}
      />
      <Button onPress={apiCall} />
      <TouchableOpacity onPress={apiCall}>
          <Text>Click Me</Text>
      </TouchableOpacity>
    </View>
  );
};
TheHound.developer
  • 396
  • 1
  • 3
  • 16
  • Ah right, so it automatically updates then without telling it too! Thanks for your code but confused as to where to put it or use it? My code shows how I am using the fetch function but can this be reused as I only took it from another piece of code. It loads on screen load so not sure how to take just that part out? Thanks – JulesUK Apr 18 '22 at 17:36
  • and also whats ? – JulesUK Apr 18 '22 at 17:45
  • And all I am getting is error : (0 , _reactNative.useState) is not a functionuseState – JulesUK Apr 18 '22 at 18:28
0

Thanks for your comments and help, I think I have a much better way of understanding a few things now. I have managed to get a load button to fetch data and display it in the way as previously managed. I know it does not look like much progress but trust me this is a big step to getting to grips with the way things work for me.

Now time to play around with it, thanks again.

The working code (well best I can do at the minute!)

import React, { useState, Component } from 'react';
import {
  StyleSheet,
  View,
  ActivityIndicator,
  FlatList,
  Text,
  StatusBar,
  Image,
  TouchableOpacity,
  ScrollView,
  SafeAreaView,
} from 'react-native';

import Icon from 'react-native-vector-icons/Entypo';
import CupertinoButtonPurple1 from '../components/CupertinoButtonPurple1';
import CupertinoButtonDanger2 from '../components/CupertinoButtonDanger2';

class App extends Component {
  state = {
    loading: false,
    dataSource: [],
    Status: 'Not loaded',
  };

  componentDidMount() {
    //  this.onPress();
  }

  onPress = () => {
    this.setState({
      loading: true,
    });

    fetch('https://www.uberfantasies.com/testv.php')
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          loading: false,
          Status: 'Loaded',
          dataSource: responseData.data,
        });

        console.log(this.state.dataSource);
      })

      .catch((error) => console.log(error)); //to catch the errors if any
  };
  FlatListItemSeparator = () => {
    return <View />;
  };
  renderItem = (data) => (
    <SafeAreaView>
      <View style={styles.container}>
        <View style={styles.rect}>
          <View style={styles.imageRow}>
            <Image source={{ uri: data.item.image }} style={styles.image} />
            <View style={styles.group2Column}>
              <View style={styles.group2}>
                <Text style={styles.bitch}>
                  Bitch from Cov sent you a mesage!
                </Text>
                <Text style={styles.loremIpsum}>
                  &quot;Hi there you Sexy Beast!&quot;
                </Text>
              </View>
              <View style={styles.loremIpsum2Row}>
                <Text style={styles.loremIpsum2}>12 Feb 2022, 6.05 pm</Text>
                <View style={styles.loremIpsum2Filler}></View>
                <View style={styles.group3}>
                  <CupertinoButtonPurple1
                    style={
                      styles.cupertinoButtonPurple1
                    }></CupertinoButtonPurple1>
                  <CupertinoButtonDanger2
                    style={
                      styles.cupertinoButtonDanger2
                    }></CupertinoButtonDanger2>
                </View>
              </View>
            </View>
          </View>
        </View>
      </View>
    </SafeAreaView>
  );

  render() {
    if (this.state.loading) {
      return (
        <View style={styles.loader}>
          <ActivityIndicator size="large" color="#0c9" />
        </View>
      );
    }
    return (
      <View style={styles.container}>
        <TouchableOpacity style={styles.button} onPress={this.onPress}>
          <Text>Click me</Text>
        </TouchableOpacity>
        <View>
          <Text>Status : {this.state.Status}</Text>
        </View>

        <FlatList
          data={this.state.dataSource}
          ItemSeparatorComponent={this.FlatListItemSeparator}
          renderItem={(item) => this.renderItem(item)}
          keyExtractor={(item) => item.id.toString()}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  button: {
    alignItems: 'center',
    backgroundColor: '#DDDDDD',
    padding: 10,
    marginBottom: 10,
  },
  loader: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
  },
  rect: {
    height: 97,
    backgroundColor: 'rgba(230,230, 230,0.57)',
    borderWidth: 0,
    borderColor: 'rgba(0,0,0,0.57)',
    marginTop: 0,
    borderBottomWidth: 1,
    borderBottomColor: '#d5d5d5',
    backgroundColor: '#f4f4f4',
  },
  image: {
    width: 80,
    height: 80,
    borderRadius: 15,
    borderWidth: 4,
    borderColor: '#ffffff',
    boxShadow: '0px 2px 4px 0px rgb(0 0 0 / 55%)',
  },
  group2: {
    width: 275,
    height: 41,
  },
  bitch: {
    fontFamily: '-apple-system,Segoe UI,Roboto,sans-serif',
    color: '#121212',
    fontSize: 14,
    height: 17,
    fontWeight: 'bold',
    marginTop: 2,
  },
  loremIpsum: {
    fontFamily: '-apple-system,Segoe UI,Roboto,sans-serif',
    color: '#121212',
    height: 17,
    width: 159,
    marginTop: 4,
  },
  loremIpsum2: {
    fontFamily: '-apple-system,Segoe UI,Roboto,sans-serif',
    color: '#121212',
    fontSize: 10,
    marginTop: 8,
  },
  loremIpsum2Filler: {
    flex: 1,
    flexDirection: 'row',
  },
  group3: {
    width: 121,
    height: 26,
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  cupertinoButtonPurple1: {
    height: 25,
    width: 57,
  },
  cupertinoButtonDanger2: {
    height: 25,
    width: 57,
  },
  loremIpsum2Row: {
    height: 26,
    flexDirection: 'row',
    marginTop: 17,
    marginRight: 3,
  },
  group2Column: {
    width: 275,
    marginLeft: 16,
  },
  imageRow: {
    height: 84,
    flexDirection: 'row',
    marginTop: 8,
    marginLeft: 4,
  },
});

export default App;
JulesUK
  • 359
  • 2
  • 11