React Native API call - react-native

How do I display results from the API call in code lower in the page?
The {data.payrollid} after Complete is not showing any value. ie: the text only shows 'Complete' with no value after it.
My returned JSON looks like this...
{"status_code":200,"payrollid":10,"message":"Success"}
When I console.log(data) I can see that the fetch worked and I can see my JSON array.
Below is my React Native code
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://www.mywebsite.ca/api/test.php')
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<>
<View>
{isLoading ? <Text>Loading...</Text> : <Text>Complete {data.payrollid}</Text> }
</View>
<View style={styles.container}>
<Text>This is my new app.</Text>
<Text>Some text</Text>
<StatusBar style="auto" />
</View>
</>
);

Your code should look something like this:
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState({});
useEffect(() => {
fetch('https://www.mywebsite.ca/api/test.php')
.then((response) => response.json())
.then((data) => setData(data))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<>
<View>
{isLoading ? <Text>Loading...</Text> :
<Text>Complete{data.payrollid}.</Text>
}
</View>
<View style={styles.container}>
<Text>This is my new app.</Text>
<Text>Your Text</Text>
<StatusBar style="auto" />
</View>
</>
);

You need to save your data in your data state.
const [data, setData] = useState({});
useEffect(() => {
fetch('https://www.mywebsite.ca/api/test.php')
.then((response) => response.json())
.then((data) => setData(data))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
And since your getting an object switch your original state to an object.

Related

how to refresh the list after submitting a form in react-native?

when redirecting to index screen after submitting a post-form, the index screen does not show the newly added item in the list, can anyone help?
here is my Customer.js page
export default function Customer({ navigation }) {
const [customers, setCustomers] = useState([]);
const [isLoading, setLoading] = useState(true);
const getCustomers = async () => {
try {
const response = await fetch("http://localhost:3001/api/customers");
const json = await response.json();
setCustomers(json);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
getCustomers();
}, []);
return (
<View style={styles.item}>
<TouchableOpacity
onPress={() => navigation.navigate("AddCustomer")}
style={styles.btn}
>
<Text style={styles.btnText}>Add New Customer</Text>
</TouchableOpacity>
<FlatList
data={customers}
extraData={customers}
renderItem={({ item }) => (
<TouchableOpacity
onPress={() => navigation.navigate("CustomerDetails", item)}
>
<Text style={styles.item}>{item.name}</Text>
</TouchableOpacity>
)}
keyExtractor={(item) => item._id}
/>
</View>
);
}
}
and here is my AddCustomer.js page
const AddCustomer = ({ navigation, route }) => {
const [name, setName] = useState("");
const [phone, setPhone] = useState(0);
const [isGold, setIsGold] = useState(false);
const handleSubmit = async () => {
// e.preventDefault();
return await fetch("http://localhost:3001/api/customers", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: name,
phone: phone,
isGold: isGold,
}),
}).then(() => {
navigation.navigate("Customer", { customers: [name, phone, isGold] });
});
};
return (
<View>
<Text style={styles.title}>Add New Customer</Text>
<View>
<TextInput
style={styles.input}
onChangeText={(val) => setName(val)}
value={name}
placeholder="Your name"
onBlur={Keyboard.dismiss}
/>
<TextInput
style={styles.input}
onChangeText={(val) => setPhone(val)}
value={phone}
placeholder="phone number"
/>
<TextInput
style={styles.input}
onChangeText={(val) => setIsGold(val)}
value={isGold}
placeholder="is gold member"
autoCorrect={false}
autoCapitalize={false}
/>
</View>
<View style={styles.inputContainer}>
<TouchableOpacity style={styles.saveButton} onPress={handleSubmit}>
<Text style={styles.saveButtonText}>Add Customer</Text>
</TouchableOpacity>
</View>
</View>
);
};
new customer would be added and everything else work fine but the Customer page does not get re-rendered or refresh or reload.
In your Customer.js do it like below -
useEffect(() => {
const unsubscribe = navigation.addListener('focus', async () => {
getCustomers();
});
return unsubscribe ;
}, [navigation]);
import { useFocusEffect } from '#react-navigation/native';
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
getCustomers();
return () => {
// Do something when the screen is unfocused
};
}, []),
);

React native fetch api value not updating after change with useState()

as I mentioned in the title, when I select a new value in my Picker, the console show that everything is ok but my fetch don't want to update it with the new selectedValue.
If I pass manually an argument into the useState, the fetch update it but I don't know how to force it to update automatically. Here the code :
export default function Bien() {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
// problem here
const [selectedValue, setSelectedValue] = useState('tous');
const fetchValue = 'https://www.api.lereseaufoncier.fr/stock?category=' + selectedValue
// the console.log works and show the new selectedValue
console.log(fetchValue)
//but here, the query don't refresh
//if I pass 'maisons' or 'appartements' in the new state manually, it works
useEffect(() => {
fetch(fetchValue)
.then((response) => response.json())
.then((json) => setData(json ? json.table : []))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
const postLayoutComponent = data.map(table => <AEPostLayout key={table.ID} table={table}/> )
return (
<SafeAreaView>
<View style={{justifyContent: 'center', alignItems: 'center', width:'100%'}}>
<Spacer taille={30} />
<Picker
selectedValue={selectedValue}
style={{ height: 50, width: 195 }}
onValueChange={(itemValue, itemIndex) => setSelectedValue(itemValue)}
>
<Picker.Item label="Tous Nos Biens" value="tous" />
<Picker.Item label="Nos Maisons" value="maisons" />
<Picker.Item label="Nos Terrains à bâtir" value="terrains à bâtir" />
<Picker.Item label="Nos Appartements" value="appartements" />
</Picker>
<Spacer taille={10} />
</View>
<ScrollView>
{postLayoutComponent}
</ScrollView>
</SafeAreaView>
);
}
I hope someone can help me.
Thank you
Try the following:
useEffect(() => {
const fetchValue = 'https://www.api.lereseaufoncier.fr/stock?category=' + selectedValue
fetch(fetchValue)
.then((response) => response.json())
.then((json) => setData(json ? json.table : []))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, [selectedValue]);
That way, adding the dependency to useEffect tells the hook that every time selectedValue has changed, the component should re-render and re-fetch the data.
Thank you all it works. And also thank you for the link to the doc.

Why am i getting error: Too many rerenders in react native

I am trying to pass an array to another component. Data is a json object array with data in it. I know the data is there because when i click the button, the handleclick method is called and the data is displayed but when i try to pass that data as an array (seasondisplay and seasonlength) I get an error: Error: Too many re-renders. React limits the number of renders to prevent an infinite loop. How do i pass the data from the fetch as an array to the dropdown box component?
function HomeScreen({ navigation }) {
const [list, setList] = useState([]);
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
let seasons = [];
useEffect(() => {
fetch('http://localhost:3000/person', {
credentials: "same-origin"
})
.then((response) => response.json())
.then((json) => setData(json))
.catch((error) => console.log("junk" + error))
.finally(() => setLoading(false));
}, []);
const [display, setDisplay] = useState("");
const handleClick = () => {
setDisplay(
data.map((item, i) => (
<Text key={i}> {item.lastname} </Text>
)))
}
const [seasondisplay, setSeasonDisplay] = useState("");
const [seasonlength, setSeasonLengthDisplay] = useState(0);
setSeasonDisplay(
data["lastname"]
)
setSeasonLengthDisplay (
2
)
return (
<View style={styles.container}>
<View style={styles.innerContainer}>
<DropDownChoice whichDropDown="Season" HowMany={seasonlength} ItemChoices={seasondisplay} />
<DropDownChoice whichDropDown="Veggies" HowMany={4} ItemChoices={["carrots", "turnip", "peas", "corn"]} />
<DropDownChoice whichDropDown="Fruit" HowMany={3} ItemChoices={["apples", "oranges", "bananas"]} />
<Button
title="Connect to DB"
onPress={() => {
console.log("please work");
console.log(data);
handleClick();
}}
here is json:
[{"personid":11,"lastname":"cook","firstname":"ben","address":"north","city":"london"},{"personid":22,"lastname":"smith","firstname":"elaine","address":"main","city":"milton"}]
I suspect that:
You are changing state on each render by setSeasonDisplay. This state change cause re render and again in rendering you changing state. You have a loop.
function HomeScreen({ navigation }) {
const [list, setList] = useState([]);
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
let seasons = [];
useEffect(() => {
fetch('http://localhost:3000/person', {
credentials: "same-origin"
})
.then((response) => response.json())
.then((json) => setData(json))
.catch((error) => console.log("junk" + error))
.finally(() => setLoading(false));
}, []);
const [display, setDisplay] = useState("");
const handleClick = () => {
setDisplay(
data.map((item, i) => (
<Text key={i}> {item.lastname} </Text>
)))
}
const [seasondisplay, setSeasonDisplay] = useState("");
const [seasonlength, setSeasonLengthDisplay] = useState(0);
//---------- changes
useEffect(() => {
setSeasonDisplay(data["lastname"])
setSeasonLengthDisplay (2)
}, [data])
//----------------
return (
<View style={styles.container}>
<View style={styles.innerContainer}>
<DropDownChoice whichDropDown="Season" HowMany={seasonlength} ItemChoices={seasondisplay} />
<DropDownChoice whichDropDown="Veggies" HowMany={4} ItemChoices={["carrots", "turnip", "peas", "corn"]} />
<DropDownChoice whichDropDown="Fruit" HowMany={3} ItemChoices={["apples", "oranges", "bananas"]} />
<Button
title="Connect to DB"
onPress={() => {
console.log("please work");
console.log(data);
handleClick();
}}

Show ActivityIndicator in React Native?

I have a function to fetch items from an API that is inside UseEffect. And i'm looking to call this function every time the status of the selectedItem or the items changes and show an ActivityIndicator before the function returns the result. The ActivityIndicator appears when the items are uploading but not when the status of the selectedItem changes ?
I have my code like this :
export default () => {
const [items, setItems] = useState();
const [selectedItem, setSelectedItem] = useState(null);
const [isLoading, setLoading] = useState(true);
const getItems = () => {
get('/api/items').then((rep) => {
setItems(rep);
setLoading(false);
}
});
};
useEffect(() => {
getItems();
}, [selectedItem.status]);
return (
<SafeAreaView style={styles.container}>
{isLoading ? (
<View style={[styles.spinnerContainer, styles.horizontal]}>
<ActivityIndicator />
</View>
) : ((items !== [])
&& (
<SectionList
stickySectionHeadersEnabled={false}
style={{ paddingHorizontal: 20, }}
sections={items}
refreshing={isLoading}
keyExtractor={(item, index) => item + index}
...
/>
))}
</SafeAreaView>
);
};
You can try setLoading(true) inside getItems
const getItems = () => {
setLoading(true);
get('/api/items').then((rep) => {
setItems(rep);
setLoading(false);
});
};

How to display fetched data in react native

I successfully posted data in MongoDB Atlas, Now i want to display that data in my simple react native App. Data is showing in my terminal but i am not able to display data in my App.
Here is code for Get data form the db.
display(){
fetch('myUrl', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
title: responseJson,
description: responseJson
})
})
.catch((error) => {
console.error(error);
});
}
Here is the code that is not displaying the data in App
<TouchableOpacity onPress={()=>this.display()} style={styles.btn}>
<Text style={{textAlign: 'center'}}> Display </Text>
</TouchableOpacity>
<View>
<FlatList
data={this.state.title}
renderItem={({item}) => <Text>{item.title}</Text>}
keyExtractor={({id}, index) => id}
/>
</View>
Flatlist data property expects an array.
But you seem to set an object.
If your api returns an array you can make the following changes to make it work:
state = {
items:[]
}
display() {
fetch('myUrl', { method: 'GET'})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
items: responseJson
})
})
.catch((error) => {
console.error(error);
});
}
As you see I used items in state as array, and updated its value when I got response from api.
And in flatlist:
<View>
<FlatList
data={this.state.items}
renderItem={({item}) => <Text key={item._id}>{item.title}</Text>}
keyExtractor={ item => item._id}
/>
</View>
A sample codesandbox
Update your code like this:
this.state = {
responseData:[]
}
display = () => {
fetch('myUrl', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
responseData: responseJson,
})
})
.catch((error) => {
console.error(error);
});
}
inside your render function:
render(){
const { responseData } = this.state;
return(
<TouchableOpacity onPress={()=>this.display} style={styles.btn}>
<Text style={{textAlign: 'center'}}> Display </Text>
</TouchableOpacity>
<View>
<FlatList
data={responseData}
renderItem={this.renderItem}
keyExtractor={item => item.id}
/>
</View>
);
}
renderItem = ({item}) => {
const { title, id, description, date } = item;
<View key={item.id}>
<Text>{item.id}</Text>
<Text>{item.title}</Text>
<Text>{item.description}</Text>
<Text>{item.date}</Text>
</View>
}
try with return keywork
Working demo api
display(){
return fetch('myUrl', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
title: responseJson,
description: responseJson
})
})
.catch((error) => {
console.error(error);
});
}