I made a screen of a flatlist that displays a bunch of Doctors infos(name,location,Picture),when i click on a doctor view it navigates to his profil. for the moment the profil screen is just blank, but i want to pass the params so i can just display them without re doing the api call.
here is the code of the research screen where the flatlist is:
render(){
return (
<View style={styles.main_container}>
<FlatList
data={this.state.dataSource}
keyExtractor={item=> item.id.toString()}
renderItem= {({item})=> <MedItem Med={item} />} />
</View>
);
}
i created a component custom med item to style my flat list:
//Meditem.js
class MedItem extends React.Component {
render(){
const Med = this.props.Med
return (
<View style={styles.main_container} >
<View style={styles.ctr1}>
<TouchableOpacity onPress={()=>NavigationService.navigate('MedProfil')}>
<Image style={styles.img} source={require('../assets/Title.jpg')} />
</TouchableOpacity>
<TouchableOpacity onPress={()=>NavigationService.navigate('MedProfil')}>
<Text style={styles.txt}> {Med.name} </Text>
<Text style={{flexWrap:'wrap'}} > {Med.specialite} </Text>
<Text> {Med.work} </Text>
</TouchableOpacity>
</View>
<View style={styles.ctr2}>
<Text style={{textAlign:'center',marginBottom:5}}>Disponibilité</Text>
<Calendar/>
</View>
</View>
);
}
}
last this is my doctor profil screen:
export default class MedProfilScreen extends React.Component {
render(){
return(
<View>
<Text>{Med.name}</Text>
<Button title='Prendre rendez-vous' onPress={()=>{}} />
</View>
);
}
}
Can someone please help me doing this.
thank you
Send Data through navigation like this
this.props.navigation.navigate("MedProfil",
{
name:Med.name
})
Get data in MedProfil Screen
const name=this.props.navigation.getParam("name")
In your Sending component use this:
constructor(props) {
super(props);
this.navigate = this.props.navigation.navigate;
}
//Send it like this
this.navigate("MedProfilScreen", { name:Med.name });
In your receiving component
constructor(props) {
super(props);
this.params = this.props.navigation.state.params;
}
//Can access it using
console.log(this.params.name);
thank you everyone! getParam won't work for me.
i used this to solve the problem
//MedItem.js
<TouchableOpacity onPress={()=>NavigationService.navigate('MedProfil',Med)}>
and in the profil screen
//MedProfil.js
export default function MedProfilScreen({route}){
const {name,specialite,work}=route.params;
return(
<ScrollView contentContainerStyle={{flex:1,alignItems:'center'}}>
<View style={styles.ctr1}>
<Text>{name}</Text>
<Text>{specialite}</Text>
<Text>{work}</Text>
Related
I'm a beginner in React Native and struggling in passing and executing functions as props from parent to child component. Here's the code:
MainMap
import React from 'react';
import {
TouchableWithoutFeedback,
StyleSheet,
View,
Button,
FlatList,
Dimensions
} from 'react-native';
import PlaceInput from '../components/PlaceInput';
const INCREMENT = 1;
const HEIGHT = Dimensions.get('window').height
const WIDTH = Dimensions.get('window').width
class MainMap extends React.Component{
constructor(props){
super(props);
this.state={
numOfInput:[],
counter: 0,
}
this.onAddSearch = this.onAddSearch.bind(this)
this.onDeleteSearch = this.onDeleteSearch.bind(this)
}
onAddSearch(){
this.setState((state) => ({
counter: state.counter + INCREMENT,
numOfInput: [...state.numOfInput, state.counter]
}))
}
onDeleteSearch(inputId){
const items = this.state.numOfInput.filter(item => item.id !== inputId)
this.setState({
numOfInput: items
})
}
render(){
return(
<TouchableWithoutFeedback onPress={this.hideKeyboard} >
<View style={styles.container} >
<Button title='Add a location' onPress={this.onAddSearch} />
<View style={{height: HEIGHT/2 }}>
<FlatList
data={this.state.numOfInput}
keyExtractor={(item, index) => item.id}
renderItem={itemData => {
return(
<PlaceInput
key={itemData.item.id}
// id={itemData.item.id}
onDelete={this.onDeleteSearch}
showDirectionOnMap={this.showDirectionOnMap}
userLatitude={userLatitude}
userLongitude={userLongitude}
/>
)
}}
/>
</View>
</View>
</TouchableWithoutFeedback>
)
}
}
export default MainMap;
const styles = StyleSheet.create({
container:{
flex: 1
},
})
Here's the PlaceInput component
class PlaceInput extends React.Component{
constructor(props){
super(props);
... // These lines have no relation to what I'm asking so don't mind them
}
...
render(){
return(
<View style={styles.buttonContainer} >
<View style={{flex: 1, alignItems: 'center'}}>
<Text style={{fontSize: 8}}>{'\u25A0'}</Text>
</View>
<View style={{flex: 4}}>
<TextInput
autoCorrect={false}
autoCapitalize='none'
style={styles.inputStyle}
placeholder='Search your places'
onChangeText={(input) => {
this.setState({destinationInput: input});
this.getPlacesDebounced(input);
}}
value={this.state.destinationInput}
/>
{/* {predictions} */}
</View>
<View style={styles.rightCol}>
<TouchableOpacity onPress={this.props.onDelete.bind(this, this.props.id)}>
<Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>
</View>
</View>
)
}
}
What I'm trying to do:
Define a function to execute in MainMap.js (in FlatList --> PlaceInput for specific) , which is to delete an search bar( the whole PlaceInput in the FlatList) every time I click the right symbol of that search bar. The function is onDeleteSearch
The right symbol is styled in a TouachableOpacity as you can see in the PlaceInput.js component. I put it in the last View pair
However, When I click, the screen deletes all the search bars, not the one I click. Is it the problem of the id of the component PlaceInput ? Or with the way I call the props?...
Please help me !
<TouchableOpacity onPress={this.props.onDelete.bind(this, this.props.id)}>
<Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>
Don't bind, just call this.props.onDelete(this.props.id);
In MainMap, try this:
<PlaceInput
key={itemData.item.id}
// id={itemData.item.id}
onDelete={() => this.onDeleteSearch(itemData.item.id)} // here
showDirectionOnMap={this.showDirectionOnMap}
userLatitude={userLatitude}
userLongitude={userLongitude}
/>
Assuming the function:
onPressed(optionalArgument = false) {
// do something
}
You can pass a function to onPress if it does not require any arguments, i.e
onPress={onPressed} // - would work if no arguments required.
onPress={onPressed(argument)} // - will get fired on component render
onPress={()=> onPressed(argument)} // - will work as expected on button press
onPress={()=> { // - will work as expected on button press
// Multiple lines of code
onPressed(argument);
anotherFunction();
}
};
In your MainMap you are doing everything correctly, just uncomment the
// id={itemdata.item.id}
In PlaceInput, just one small change:
<TouchableOpacity onPress={() => this.props.onDelete(this.props.id)}>
<Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>
If you don't add ()=> to your onPress, the function gets called immediately, that's why you see such behaviour.
Your numOfInput is just a list of numbers, so instead of using item.id-s use item directly.
Here:
const items = this.state.numOfInput.filter(item => item !== inputId)
And here
<PlaceInput
key={itemData.item}
// id={itemData.item}
...
/>
I'm trying to obtain a loader when a button is clicked (for a signup) without create another page (only to show the loader).
How can I do??
This is my code and what I tried (but it doesn't appears)
class Signup extends Component {
constructor(props) {
super(props);
this.state = {
//code about signup
isLoading: false
};
}
showLoader = () =>{
this.setState({ isLoading: true})
this.registrazione()
}
registrazione() {
//code about signup
}
render() {
return (
<View style={style.container}>
//code about signup
<View style={style.footer}>
<TouchableOpacity
style={[style.button, style.buttonOK]}
onPress={() => this.showLoader()}
>
<Text style={[style.buttonTesto]}>Signup</Text>
</TouchableOpacity>
<ActivityIndicator animating={this.state.isLoading} size="large" color="#56cbbe" />
</View>
</KeyboardAwareScrollView>
</View>
</View>
);
}
}
First of all you have one closing View tag that is not needed.
Assuming that's just mistake in question, you could do it with JS ternary operator. Like this:
<View style={style.container}>
//code about signup
<View style={style.footer}>
{(!this.state.isLoading) ? <TouchableOpacity
style={[style.button, style.buttonOK]}
onPress={() => this.showLoader()}
>
<Text style={[style.buttonTesto]}>Signup</Text>
</TouchableOpacity> : <ActivityIndicator animating={this.state.isLoading} size="large" color="#56cbbe" />}
</View>
</KeyboardAwareScrollView>
</View>
You can learn more about ternary operators here
This should replace your button with loading animation.
Don't hesitate to ask any more questions if you have any! I'm glad to help!
I need to change data between 2 different screens using react-navigation. The default screen shows the notes and adding the note is done in a separate screen using text input. Adding screen needs to give an array to default screen.
I managed to give some parameter but adding screen should pass an array.
Adding note class. Text input makes a new addition to notes state.
class AddScreen extends React.Component {
constructor(props) {
super(props);
}
state = {
textInputComponent: '',
notes: [
{
text: "Note 1"
}
]
}
return(
<View>
<TextInput style = {styles.inputField} placeholder="Write the note here"
onChangeText={(textInputComponent) => this.setState({textInputComponent})}
value = {this.state.textInputComponent} />
<TouchableOpacity style = {styles.customBtn2}
onPress={() => {this.addToList(this.state.textInputComponent)}}>
<Text style = {styles.customBtnText}>Add note </Text>
</TouchableOpacity>
<TouchableOpacity style = {styles.customBtn3}
onPress={() => navigate('Notes', {note: this.state.notes})}>
<Text style = {styles.customBtnText2}>Add notes </Text>
</TouchableOpacity>
</View>
);
The default screen where notes should be showing
class NoteList extends React.Component {
constructor(props) {
super(props)
this.state = {
notes: []
}
}
makeNoteList(note){
this.state.notes.push(note);
console.log(this.state.notes);
return (
<View>
{this.state.notes.map(note => {console.log(note.text)})}
</View>
)
}
render() {
const {navigate} = this.props.navigation;
const {navigation} = this.props;
const note = navigation.getParam('note', 'No notes');
return(
<ScrollView style = {styles.background}>
<View style={{flex: 1,
flexDirection: 'column',
alignItems: 'center'}}>
{this.makeNoteList(note)}
</View>
<View style={{flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end'}} >
<TouchableOpacity style = {styles.customBtn}
onPress={() => navigate('AddNotes', {name: 'AddNotes'})}>
<Text style = {styles.customBtnText}>List of notes </Text>
</TouchableOpacity>
</View>
</ScrollView>
)
}
}
I can't seem to map the parameters that AddScreen class gives. Default screen should map this given array to show notes. I'm aware that these code snippets are missing some curly brackets and maybe brackets to shorten these snippets so here you can see the whole code: https://snack.expo.io/rk4opjbqE
When i press the <TouchableOpacity> Button, i want the value 'abc' to be appended to the array selectedTags and then <Text> {this.list()} </Text> will print out my array.
But now when i press the Button, nothing display out.
Can anybody know what is the problem with my code?
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
selectedTags: []
}
}
list() {
return this.state.selectedTags.map(function(tags, i){
return(
<View key={i}>
<Text>{tags.name}</Text>
</View>
);
});
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => this.state.selectedTags.push('abc')} key = {1} style={styles.buttonContainer}>
<Text style={styles.buttonText}> Button </Text>
</TouchableOpacity>
<Text> {this.list()} </Text>
</View>
);
}
}
This is because you never call setState, which would trigger re-render of your component.
instead of using:
onPress={() => this.state.selectedTags.push('abc')}
try:
onPress={() => this.setState({selectedTags: this.state.selectedTags.concat('abc')})}
The function list only push data in array but does not rerender the view, todo so you have to use setState or forceUpdate.
You can implement the onpress function like this.
onPress = () =>{
this.state.selectedTags.push("abc");
this.setState({selectedTags : this.state.selectedTags});
}
I'm trying to create IndicatorViewPager with three parts.
the problem that I can't see the content of each page. Below my code.
export default class Reservations extends Component {
render() {
return (
<View style={{flex:1}}>
<IndicatorViewPager
style={{flex:1, paddingTop:20, backgroundColor:'white'}}
indicator={this._renderTitleIndicator()}
>
<View style={{backgroundColor:'cadetblue'}}>
<Text>page one</Text>
</View>
<View style={{backgroundColor:'cornflowerblue'}}>
<Text>page two</Text>
</View>
<View style={{backgroundColor:'#1AA094'}}>
<Text>page three</Text>
</View>
</IndicatorViewPager>
</View>
);
}
_renderTitleIndicator() {
return <PagerTitleIndicator titles={['one', 'two', 'three']} />;
}
I have the title for each part but the content is hidden. Thank you for your help.