I want to pass data to another screen on button click. I was using router-flux and it was working just fine, but on react-navigation it won't work.
So, on router-flux, on button click, it calls this function:
onSearch() {
fetch(`URL`, {
method: 'GET',
})
.then((response) => { return response.json() } )
.then((responseJson) => {
Action.results({data: responseJson});
})
.catch((error) => {
Alert.alert("0 Cars!");
});
}
But on react-navigation, if I change the code to this:
onSearch() {
fetch(`URL`, {
method: 'GET',
})
.then((response) => { return response.json() } )
.then((responseJson) => {
this.props.navigation.navigate('Resultados', { data: responseJson });
})
.catch((error) => {
Alert.alert("0 Cars!");
});
}
it won't work, I always get the alert "0 Cars!".
What am I doing wrong? On router-flux it was pretty straightforward.
This is how I call onSearch function:
<Button onPress={this.onSearch} style={{backgroundColor: '#f48529', width: 140, borderRadius: 30, height: 40}} >
<Text style={{color: 'white', fontFamily: 'rubik-light', fontSize: 17}}>Search</Text>
<Icon size={15} name={'search'} color={'white'} />
</Button>
Try changing your onPress={this.onSearch} to onPress={this.onSearch.bind(this)}
And also
Try
onSearch() {
const { navigate } = this.props.navigation;
fetch(`URL`, {
method: 'GET',
})
.then((response) => { return response.json() } )
.then((responseJson) => {
navigate('Resultados', { data: responseJson });
})
.catch((error) => {
Alert.alert("0 Cars!");
});
}
Related
I am using Flatlist to show a list of Date. I have created a component DateList to view the list of item.
I have already called an API apiFreelancerDate. However, currently I am trying to call another function through the component (which I will later use it for second API call).
Date screen:
apiFreelancerDate = () => {
let self = this;
AsyncStorage.getItem('my_token').then((keyValue) => {
axios({
method: 'get',
url: Constants.API_URL + 'user_m/confirmation_date/',
params: {
freelancer_id: self.props.navigation.state.params.fr_id,
},
responseType: 'json',
headers: {
'X-API-KEY': Constants.API_KEY,
'Authorization': keyValue,
},
})
.then(function (response) {
self.setState({
dataSource: response.data.data,
isLoading: false,
});
})
.catch(function (error) {
console.log('Error Response: ', error.response);
});
}, (error) => {
console.log('Error', error) //Display error
});
}
//test function call
testFunc = () => {
console.log('test function called');
}
//test function call
viewFreelancerDate() {
const { dataSource } = this.state;
return (
<View>
{<FlatList
data={dataSource}
keyExtractor={({ id }, index) => index.toString()}
renderItem={({ item }) => <DateList {...item} functionCall={this.testFunc}/>}
/>}
</View>
);
}
DateList component:
<TouchableOpacity
style={{ flex: 1 }}
onPress={() => this.props.navigation.navigate('masterFreelancerTime')}
>
<Text style={styles.textStartDate}>{this.props.date_start}</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.activeBorder}
onPress={() => {
this.props.functionCall;
const newStatus = !this.state.status;
this.setState({
status: newStatus,
});
console.log('status: ', this.state.status);
console.log('Date: ', this.props.date_start);
}}
>
<Text style={styles.active_inactive}>{this.state.status ? "INACTIVE" : "ACTIVE"}</Text>
</TouchableOpacity>
I am very new to this so any help would be appreciated and I don't know if it's the right way to do it.
My main purpose is that I want to add a function call that will call an API which will show the state "INACTIVE" : "ACTIVE" based on what's in the database. And upon pressing/tapping, the "INACTIVE" : "ACTIVE" will toggle and at the same time it'll update it's value in the database.
You are mostly on right track. Although you may want to keep few things in mind.
e.g.
<TouchableOpacity
style={styles.activeBorder}
onPress={() => {
this.props.functionCall;
const newStatus = !this.state.status;
this.setState({
status: newStatus,
});
console.log('status: ', this.state.status);
console.log('Date: ', this.props.date_start);
}}
>
This is an overoptimisic assignment to state.status before api call finishes. What if the api call fails, in that case, your status is not in-sync with database. You can update the state without waiting for API to return the response, but you should update the state again in case API fails.
If you don't need optimistic state update, then you can do something like following:
Date screen:
//test function call
testFunc = () => {
console.log('test function called');
const dataSource = makeAPiCallAndGetUpdatedApiSource();
this.setState({ dataSource });
}
//test function call
viewFreelancerDate() {
const { dataSource } = this.state;
return (
<View>
{<FlatList
data={dataSource}
keyExtractor={({ id }, index) => index.toString()}
renderItem={({ item }) => <DateList {...item} functionCall={this.testFunc}/>}
/>}
</View>
);
}
DateList component:
constructor(props) {
this.state = {
status: props.status
};
}
...
componentDidUpdate() {
this.setState({ status: this.props.status })
}
...
<TouchableOpacity
style={styles.activeBorder}
onPress={() => {
this.props.functionCall();
}}
>
This way, after the api call, state of date screen will be updated ... which in turn will update DateList component, which will update the state of component.
I am navigating to this 'History' tab from a side menu in React Native Navigation. Got a username for which I get all the 'bookings' made, but I can see in the warning tab that there are countless requests being made even after the component has been mounted, so there's an infinite loop probably caused by setState. Where should I call getHistory(), as in to make only one request, unless of course the component is reloaded. Thank you!
constructor(props){
super(props);
this.state = {
loggedUser: 'none',
bookingsInfo: []
}
}
getData = async () => {
try {
const value = await AsyncStorage.getItem('loggedUser')
if(value !== null) {
this.setState({
loggedUser: value
})
}
} catch(e) {
console.error(e);
}
}
getHistory() {
fetch('https://porsche.e-twow.uk/reactnative/istoric.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Cache-Control': 'no-cache, no-store'
},
body: JSON.stringify({
username: this.state.loggedUser
})
})
.then((response) => response.json())
.then((data) => {
this.setState({
bookingsInfo: data
});
})
.catch((error) => {
console.error(error);
});
}
componentDidMount() {
this.getData();
}
render() {
this.getHistory();
return (
<View style={styles.view}>
<ScrollView style={styles.scrollView}>
{
this.getHistory()
}
{
this.state.bookingsInfo ? this.state.bookingsInfo.map((item, index) => {
return (
<View style={styles.mainButton} key={item.id_scooter}>
<Text style={styles.mainButtonText}>Scooter-ul {item.id_scooter}</Text>
<Text style={styles.mainButtonText}>Data start: {item.start}</Text>
<Text style={styles.mainButtonText}>Data final: {item.end}</Text>
</View>
)
}) : null
}
</ScrollView>
<Footer/>
</View>
);
}
}
you are setting state in render.Calling setState here makes your component a contender for producing infinite loops.
place getHistory in componentDidMount .
componentDidMount() {
this.getHistory();
}
I'm using react-native-popup-dialog. There is a single button within popup (yes). I want to close the button at same time I want to submit values to server.Now after clicking on yes button values get submit to server. How do I write close function at same onPress method? following is my code
onPressYes = (workType) => {
AsyncStorage.getItem('userid').then((usid) =>{
this.setState({
'userid': usid
});
console.log(usid);
fetch(GLOBAL.USER_REQUEST,{
method:'POST',
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
workType,
usid
})
})
.then(response => response.json())
.then((responseData) => {
this.setState({
data:responseData
});
});
})
}
popUpDialog = (id, workType) => {
this.setState ({
workType: workType
});
this.popupDialog.show();
}
render(){
return(
<PopupDialog ref={popupDialog => {
this.popupDialog = popupDialog;
}}
dialogStyle={{ backgroundColor: "#FFFFFF", height: 180, width:300, borderWidth:1,padding:10}}
overlayBackgroundColor="#fff" onDismissed={() => {
}}>
<View style={styles.dialogContentView}>
<Text style={{fontSize:18, margingTop:10,color:"#000000"}}>Are you sure you want to submit?</Text>
<View style={{alignSelf:'center'}}>
<View style={styles.button_1}>
<Button title="Yes" color="#8470ff" onPress={() => this.onPressYes(workType)}/>
</View>
);
According to your code, you can use this.popupDialog.dismiss() instance method to hide a dialog:
onPressYes = (workType) => {
this.popupDialog.dismiss(); // action to close a dialog
AsyncStorage.getItem('userid').then((usid) =>{
this.setState({
'userid': usid
});
console.log(usid);
fetch(GLOBAL.USER_REQUEST,{
method:'POST',
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
workType,
usid
})
})
.then(response => response.json())
.then((responseData) => {
this.setState({
data:responseData
});
});
})
}
Using visible props to control it.
import Dialog, { DialogContent } from 'react-native-popup-dialog';
import { Button } from 'react-native'
<View style={styles.container}>
<Button
title="Show Dialog"
onPress={() => {
this.setState({ visible: true }); // here
}}
/>
<Dialog
visible={this.state.visible} // here
onTouchOutside={() => {
this.setState({ visible: false });
}}
>
<DialogContent>
{...}
</DialogContent>
</Dialog>
</View>
Ref: https://github.com/jacklam718/react-native-popup-dialog
I'am trying to Update and Delete some items by ID upon tap/click of Update And Remove buttons. But my problems is, I'm not sure what is the proper approach doing a "fetch with a state(or anything) for the ID's".
With these approach, I have errors. (Ex: undefined is not an object ...)
Without these, I have nothing. I'am well aware of that because I'm not referring to anything. So I have to use ID. But I don't know the approach.
Please help, anything will be appreciated. :)
Here is my code
Settlement.js
export default class Settlement extends Component {
constructor(props){
super(props)
this.state = {
...
deleteOrder: '',
numOrder: '',
};
}
submit = () => {
this.state.numOrder = item.order_id; // here's my fetch with state
fetch('http://192.168.254.***:****/SendOrder/update' + this.state.numOrder, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
spcl_req: this.state.SplOrder,
order_quantity: this.state.count,
order_type: this.state.DineIn,
})
}).then(res => res.json())
.then((responseJson) => {
Alert.alert(JSON.stringify(responseJson))
console.log(responseJson);
})
.catch(error => console.error('Error:', error))
}
delete = () => {
this.state.deleteOrder = item.order_id; // here's my fetch with state
fetch('http://192.168.254.***:****/SendOrder/delete_order/' + this.state.deleteOrder, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
order_id: this.state.deleteOrder
})
}).then((responseData) => {
Alert.alert(JSON.stringify(responseData))
console.log(responseData.rows)
}).done();
}
render() {
const { params } = this.props.navigation.state;
return (
<View>
<FlatList
...
renderItem = {({ item }) =>
<View>
....
<View>
<TouchableOpacity
onPress = { () => this.submit() }>
<Text>UPDATE</Text>
</TouchableOpacity>
<TouchableOpacity
onPress = { () => this.delete() }>
<Text>REMOVE</Text>
</TouchableOpacity>
</View>
</View>
}/>
</View>
)
}
}[![enter image description here][1]][1]
You broke a couple of concepts in React.
this.state.numOrder = item.order_id;
This line will not update your state
What's in the item in this line? renderItem = {({ item }) =>
Perhaps in this object there is an identifier, which must be passed as an argument to your functions
How to make load more with FlatList of React Native (Not infinite)
I've done this, but unfortunately it loads as infinitely.
This is my code snippet
<FlatList
data={this.props.data}
renderItem={({ item, separators }) => (
<TouchableHighlight
onPress={() => this._onPress(item)}
onShowUnderlay={separators.highlight}
onHideUnderlay={separators.unhighlight}
>
<Text> {item.title} </Text>
</TouchableHighlight>
)}
keyExtractor={item => item.id}
ListFooterComponent={this.renderFooter}
onEndReached={this.props.handleLoadMore}
onEndThreshold={0}
/>
And my handleLoadMore
handleLoadMore = () => {
console.log("test"); // <---- this line run infinitely
fetch(url, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(filters)
})
.then(response => response.json())
.then(responseJson => {
this.setState({
itemData: [
...this.state.itemData,
...responseJson.estate_list
],
itemPage: this.state.itemPage + 1
});
})
.catch(error => {
console.error(error);
});
};
There is issue when loading data in FlatList and your onEndReached handler will be called when the view is re-rendered. Try setting a flag like this :
constructor(props){
super(props);
this.state = {
hasScrolled: false
}
}
Then add this method :
onScroll = () => {
this.setState({hasScrolled: true})
}
Hook it up to FlatList:
<FlatList
onScroll={this.onScroll}
Finally load only when scrolled :
handleLoadMore = () => {
if(!this.state.hasScrolled){ return null; }
//here load data from your backend
}
constructor(props){
super(props);
this.state = {
loading: true
}
}
<FlatList
onEndReached={this.handleLoadMore}/>
handleLoadMore = () => {
if(!this.state.loading){ return null; }
this.setState({
page: this.state.page + 1,
loading: false
}, () => {
this.loadProducts();
});
};
loadProducts(catId,userkey){
$this.setState({
loading:true
});
}