Cannot display array in React Native - javascript

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});
}

Related

Passing data to routes navigation React Native

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>

How to pass and execute functions as props in class Component in React Native?

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}
...
/>

How do I navigate between List and Item?

I am trying to open an item from my list but my item code is in another js. When I try to use onPress method there is no action. Also I am using Swipeout.
Here is my JobList.js where I am rendering the list of my items.
class JobList extends Component {
onJobDetails = (job) => {
this.props.navigate('JobDetails', job);
}
render() {
const { navigation } = this.props;
var renderJobs = () => {
return this.props.jobs.map((job) => {
return (
<JobItem
key={job._id}
title={job.title}
shortDescription={job.shortDescription}
logo={job.avatar}
company={job.company}
id={job._id}
dispatch={this.props.dispatch}
onPress={() => this.onJobDetails(job)}
/>
)
})
}
return (
<View style={styles.container}>
<ScrollView>
{renderJobs()}
</ScrollView>
</View>
);
}
};
And here is my JobItem.js
class JobItem extends Component {
render() {
return (
<Swipeout {...swipeSettings}>
<View style={styles.jobContainer}>
<View>
<Text style={styles.postTitle}>{this.props.title}</Text>
<Text style={styles.postShortDescription}>{this.props.shortDescription}</Text>
</View>
<View>
<Image
style={styles.postLogo}
source={{uri: '' + this.props.logo + ''}}/>
</View>
</View>
</Swipeout>
)
}
};
Any idea how shall I fix this?
You need to pass onPress prop to the child component in order for it to work.
<Swipeout {...swipeSettings}>
<TouchableWithoutFeedback onPress={this.props.onPress}>
//... other children here
</TouchableWithoutFeedback>
</Swipeout>

how to add pull to refresh with redux react native

I wanna add pull to refresh but i dont know what to call from from _Refresh(). I have action, constants and reducers in another page. How can i recall the api.
thanks for help in advance.
I wanna add pull to refresh but i dont know what to call from from _Refresh(). I have action, constants and reducers in another page. How can i recall the api.
thanks for help in advance.
class HomeworkList extends Component {
constructor(props){
super(props);
this.state = {
getHW : null,
refreshing: false,
appState: AppState.currentState,
months : ["Jan","Fev","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
}
}
_onRefresh() {
this.setState({refreshing: true});
}
componentDidMount(){
this.props.getHomework();
}
render() {
const {homework,isFetching} = this.props.homework;
if(isFetching){
return(
<View>
<ActivityIndicator
color = '#bc2b78'
size = "large"
/>
</View>
)
}
else{
return (
<ScrollView style={styles.container} refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}>
<View style={styles.filterView}>
<View style={{flexDirection:'row'}}>
<Icon size={20} name="ios-options" color="#000000" /><Text style={[{color:"#333333"},mainStyles.postTitle]}> FILTER BY</Text>
</View>
<View>
<ScrollView
horizontal={true}
showsHorizontalScrollIndicator={false}
>
{
this.state.months.map((item,i)=>{
return(
<TouchableHighlight key={i} style={styles.filterItem} onPress={() => {}} underlayColor={"#de0000"}><Text >{item}</Text></TouchableHighlight >
)
})
}
</ScrollView>
</View>
</View>
<View style={[styles.titleView,mainStyles.coloredBackground]}>
<TouchableOpacity
>
<Text style={styles.title}>
THIS MONTH
</Text>
</TouchableOpacity>
</View>
<View style={styles.viewPadding}>
{
homework.length ? (
homework.map((item, index) => {
return(
<TouchableOpacity
onPress={() => this.props.navigate('Chat', { title: item })}
key={item.id}
>
<Text style={[styles.listItems,{borderColor:randomHex()}]}>
{item.date}
</Text>
</TouchableOpacity>
)
})
):null
}
</View>
</ScrollView>
);
}
}
}
function mapDispatchToProps(dispatch){
return{
getHomework: () => dispatch(fetchHomeworkFromApi()),
getNaviagationName:()=>dispatch(getNaviagationName())
}
}
function mapStateToProps(state){
return{
homework: state.homework
}
}
export default connect(mapStateToProps,mapDispatchToProps)(HomeworkList);
Dispatch a refresh action inside the refresh callback.
This action should then dispatch any number of other actions to "re fresh" like fetchHomeworkFromApi and getFreshData. Don't re-fetch things that make no sense to refresh.
Inside your reducers make sure that when fresh data arrives, it replaces the old. (Avoid situations where new data is appended to old data)
Very simple, assuming you have API call defined in your redux action, hooked up with redux thunk, something like below
// Action.js
const reduxAction = () => {
return async dispatch => {
dispatch({ type: IS_LOADING });
//Call backend API
const result = axios.xxx();
dispatch({ type: GOT_RESULT, payload: result });
}
}
The above is the very standard API calling from redux, nothing to do with pull to refresh yet.
Now since we have a redux Action for our component, and that you have RefreshControl, you need to update your `_
_onRefresh() {
this.props.reduxAction();
}
As for your RefreshControl, instead of using localState, use the loading state from your redux, something like below
<RefreshControl
refreshing={this.props.refreshing} //Use the one from redux, not component state
onRefresh={this._onRefresh.bind(this)}
/>

null is not an object (evaluating 'this.state.noteArray') - React Native

Why im receiving this error, but I already add the Constructor at my class.
the error just appear when I execute the android-run start and im getting this error.
null is not an object (evaluating 'this.state.noteArray')
export default class testPoject extends Component {
constructor(props) {
super(props);
this.state = {noteArray: []}
}
render() {
let notes = this.state.noteArray.map((val, key) => {
return <Note key={key} keyval={key} val={val} deleteMethod={ () => this.deleteNote(key)} />
});
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerText}>TODO LIST </Text>
</View>
<ScrollView style={styles.scrollConainer}>
</ScrollView>
<View style={styles.footer}>
<TouchableOpacity style={styles.addButton}>
<Text style={styles.addButtonText}>
+
</Text>
</TouchableOpacity>
<TextInput style={styles.noteInputText}
placeholder="> Note"
placeholderTextColor="#FFF"
underlineColorAndroid="transparent"
numberOfLines = {3}
/>
</View>
</View>
);
}
}
Well,
Do one thing and it will work. Add a constructor and in that constructor declare the state.
constructor() {
super();
this.state = {
noteArray:[{ 'note': 'Bingo'}],
noteText:'',
}
}
Why are you passing a val and key to your map function? noteArray is an array, not an object with key, value pairs. Ether write noteArray as noteArray: {} or change your map function to work with a single element.

Categories

Resources