Rerender Component on Function Return - javascript

I have a class function that filters my props then uses it to render a deckswiper. The problem is that the function doesn't complete by the time the deckswiper renders so it renders a blank deckswiper. Is there a way that I can either make it rerender when the deck is complete or make the function asynchronous? Or should I be filtering this data elsewhere? When I first refresh the page the deckswiper is blank, then if I click my button to add more data it seems to work.
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Container, View, DeckSwiper, Text, Spinner, Button, Icon } from 'native-base';
import { findDogs, addDog, blacklistDog } from '../actions';
import SwipeDogItem from './SwipeDogItem';
class SwipeDogSelect extends Component {
componentWillMount() {
this.props.findDogs();
}
shouldComponentUpdate(nextProps) {
if(nextProps.blacklist !== this.props.blacklist) {
return false;
}
return true;
}
dogBreedString(breed) {
if (Array.isArray(breed)) {
let breedString = '';
for (let i = 0; i < breed.length; i++) {
breedString += `${breed[i].$t}, `;
}
return breedString.slice(0, -2);
}
return breed.$t;
}
filterDogs() {
const { dogs, gender, selectedBreeds, blacklist, size } = this.props;
return dogs.filter((pet) => {
return blacklist.indexOf(pet.id.$t) === -1 &&
(selectedBreeds > 248 || Object.values(pet.breeds.breed).filter(val => !selectedBreeds.includes(val)).length < 1) &&
(gender === 'either' || pet.gender.$t === gender) &&
(size === 'any' || pet.size.$t === size);
});
}
renderDeckSwiper() {
console.log(this.props.dogs);
if (this.props.findingDogs || typeof this.props.dogs === 'string') {
return (<Spinner color='black' />);
} else if (this.props.dogs === undefined) {
return (
<Text>No dogs found.</Text>
);
}
return (
<DeckSwiper
ref={mr => (this._deckSwiper = mr)}
dataSource={this.filterDogs()}
renderItem={dog => {
return (
<SwipeDogItem
dog={dog}
breed={this.dogBreedString(dog.breeds.breed)}
/>
);
}}
renderEmpty={() => {
return (<Text>No dogs found. Try less filters or refreshing.</Text>);
}}
onSwipeRight={(dog) => { this.props.addDog(dog); }}
onSwipeLeft={(dog) => { this.props.blacklistDog(dog.id.$t); }}
loop={false}
/>
);
}
render() {
return (
<Container>
<View>
{this.renderDeckSwiper()}
</View>
<View
style={styles.buttonViewStyles}
>
<Button
style={styles.buttonsStyles}
rounded
large
onPress={() => {
this.props.blacklistDog(this._deckSwiper._root.state.selectedItem.id.$t);
this._deckSwiper._root.swipeLeft();
}}
>
<Icon style={styles.buttonIconStyles} name="close" fontSize='40' color='red' />
</Button>
<Button
warning
rounded
style={styles.buttonsStyles}
large
onPress={() => this.props.findDogs()}
>
<Icon style={styles.buttonIconStyles} name='refresh' />
</Button>
<Button
rounded
style={styles.buttonsStyles}
large
danger
color='red'
onPress={() => {
this.props.addDog(this._deckSwiper._root.state.selectedItem);
this._deckSwiper._root.swipeLeft();
console.log(this._deckSwiper._root);
}
}
>
<Icon style={styles.buttonIconStyles} color='red' name="heart" active />
</Button>
</View>
</Container>
);
}
}
const styles = {
buttonsStyles: {
borderWidth: 1,
borderColor: 'rgba(0,0,0,0.2)',
alignItems: 'center',
justifyContent: 'center',
width: 75,
height: 75,
borderRadius: 100,
marginTop: 100,
},
buttonViewStyles: {
flexDirection: "row",
flex: 1,
position: "absolute",
bottom: 15,
left: 15,
right: 15,
justifyContent: "space-between",
padding: 15
},
buttonIconStyles: {
fontSize: 45,
}
};
const mapStateToProps = state => {
const { selectedBreeds, gender, size } = state.settings;
const { dogs, findingDogs } = state.findDogsReducer;
const { blacklist } = state.dogs;
return {
dogs,
findingDogs,
blacklist,
selectedBreeds,
gender,
size
};
};
export default connect(mapStateToProps, { findDogs, addDog, blacklistDog })(SwipeDogSelect);

I ended up switching to another swiper because native base's swiper was causing the issue.

Related

Undefined is not an object(evaluating '_this2.state') [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 1 year ago.
I´m trying to render a form but I have some issues in the function ´getQuestions´.
The problem is with the colors, I can´t defined colors to the styles. (eg color:this.state.theme.someColor) I got an error ( Undefined is not an object(evaluating '_this2.state')
Instead I have to defined a variable and then passed to the color or backgroundColor. eg var fontColor = this.state.theme.someColor ant then in the return color:fontColor (psd: the others styles are working pretty well).
Also in the onPress in the Radio input I can´t call functions or the state for the same reason. What I am doing wrong? Thanks in advance for your help
The code:
import React, { Component } from 'react';
import {
Text,
StyleSheet,
ScrollView,
View,
ActivityIndicator
} from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
import WebService from '../WebService/WebService';
import { decode } from 'html-entities';
import { NativeBaseProvider, Box, Radio, Checkbox, HStack } from 'native-base';
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';
import AwesomeButtonRick from "react-native-really-awesome-button/src/themes/rick";
class QuizComponent extends Component {
constructor(props) {
super(props);
const params = this.props.route.params;
this.webservice = new WebService();
this.state = {
load: true,
item: params.item,
questions: params.item.quiz[0].questions,
userAnswers: [],
theme: {
primary: "#FFFFFF",
font_color: "#000000",
secondary: "#FFFFFF",
contrast: "#CCCCCC"
}
}
}
componentDidMount() {
this.getData();
}
renderLoading = () => {
return (
<View style={[styles.load, {
backgroundColor: "#cccccc"
}]}>
<ActivityIndicator size="large" color="#ffffff" />
</View>
);
}
getData = async () => {
this.setState({ load: true })
try {
const user = await AsyncStorage.getItem('CurrentUser')
const platform = await AsyncStorage.getItem('Platform')
const userObject = JSON.parse(user)
const platformObject = JSON.parse(platform)
if (user) {
this.setState({
host: platformObject.host,
plataforma: platformObject.name,
user: userObject,
username: userObject.username,
user_id: userObject.userId,
api_key: userObject.apiKey,
theme: {
primary: platformObject.theme.primary,
font_color: platformObject.theme.accent,
secondary: platformObject.theme.secondary,
contrast: platformObject.theme.extra
}
})
setTimeout(() => {
this.setState({ load: false })
}, 500)
} else {
}
} catch (e) {
console.error(e)
}
}
getQuestions = () => {
var secondary = this.state.theme.secondary
var font_color = this.state.theme.font_color
var contrast = this.state.theme.contrast
console.log(this.state.userAnswers)
return (
<ScrollView style={[{
width: '100%',
maxHeight: '100%'
}]}>
{
this.state.questions.map(function (qIndex, index) {
switch (qIndex.type) {
case '1':
return (
<Box key={index} style={[styles.container_box]}>
<Text style={[styles.question], {
backgroundColor: this.state.theme.secondary,
color: font_color,
padding: '2%',
borderRadius: 5
}}>{decode(qIndex.question)}</Text>
<Box style={[{ marginTop: '2%' }]}>
<HStack>
<Radio.Group>
{qIndex.answers.map(function (ansIndex, index1) {
return (
<Radio
key={index + '-' + index1}
value={ansIndex.id}
onPress={() => {
console.log('press')
}}
>
<Text style={styles.answer, {
color: font_color,
marginBottom: '2%'
}}>
{' ' + decode(ansIndex.answer.replace('<p>', '').replace('</p>', ''))}
</Text>
</Radio>
)
})}
</Radio.Group>
</HStack>
</Box>
</Box>
)
break;
default:
return (
<View>Algo</View>
)
break;
}
})
}
<AwesomeButtonRick
style={[{
alignSelf: "center",
marginTop: '10%',
marginBottom: '20%'
}]}
backgroundColor={secondary}
backgroundDarker={contrast}
textColor={font_color}
paddingHorizontal={70}
textSize={18}
onPress={() => { console.log('hola') }}
>Terminar
</AwesomeButtonRick>
</ScrollView>
)
}
render() {
if (this.state.load === true) {
return(
<NativeBaseProvider>
{this.renderLoading()}
</NativeBaseProvider>
)
}else{
return (
<NativeBaseProvider>
<Box style={[styles.main_box], { backgroundColor: this.state.theme.primary,}}>
{this.getQuestions()}
</Box>
</NativeBaseProvider>
);
}
}
}
export default QuizComponent;

Why don't multiple items fit vertically in the React native View?

I have an App in which there is a View with two CardViews that each direct me to different screens.
Now I have added another CardView, and there are already three.
The problem is that neither in iOS nor in Android the third of the CardView is shown in full, only part of it is shown as I show in the screenshot.
I have tried ScrollView since it is a list of few items and Scroll works, but it does not stop and when I release my finger from the screen, the screen returns to its initial position.
Also the scroll does the entire screen, including the Header, which should not be the case
I have also tried using FlatList, but I get errors
I have played with the View styles, but I do not understand the problem that is offered so that the Scroll does not work within the View.
I show the code of the file, with the third of the CardView added.
How can I correct this and make the screen Scroll to be able to access all the CardViews on the screen?
import React, { Component } from "react";
import _ from "lodash"
import ToolBar from "../../../component/ToolBar";
import styleApp from "../../../../res/style/style";
import AppText from "../../../component/Text";
import { strings } from "../../../config/i18n/i18n";
import CardView from "../../../component/CardView";
import { sizeWidth } from "../../../util/Size";
import NavigationActions from "../../../router/NavigationActions"
import {
AsyncStorage,
Image,
StyleSheet,
View,
FlatList,
ScrollView,
List,
SectionList
} from "react-native"
export default class PaintScreen extends Component {
state = {
isLoading: true,
studiedAlphabet: [],
studiedNumber: []
};
componentDidMount() {
AsyncStorage.getAllKeys((error, keys) => {
AsyncStorage.multiGet(keys, (error, stores) => {
const alphabets = [];
const numbers = [];
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
if (store[i] != null) {
//data provide is [key: value] - value [[]]
if (store[i][0] == "learned_alphabets") {
alphabets.push(JSON.parse(store[i][1]));
}
if (store[i][0] == "learned_numbers") {
numbers.push(JSON.parse(store[i][1]));
}
}
if (i == keys.length - 1) {
this.setState({
isLoading: false,
studiedAlphabet: alphabets[0],
studiedNumber: numbers[0]
});
}
});
});
});
}
render() {
if (!this.state.isLoading) {
return (
<View style={styles.containerMio}>
<Image
style={styles.backgroundImage}
source={require("../../../../res/images_paint/background/backgroundA_2x.png")}
/>
<Image
style={styles.newPaintImage}
source={require("../../../../res/images_paint/mainScreen/new_paint_ball_2x.png")}
/>
{this.renderToolbar()}
<View
style={{
width: "100%",
alignItems: "center",
position: "absolute",
top: sizeWidth(20)
}}
>
{this.renderAnimal()}
{this.renderObject()}
{this.renderAnimal()}
</View>
</View>
)
} else {
return null;
}
}
renderToolbar = () => {
return (
<ToolBar
center={
<AppText style={styleApp.ToolBarText}>
{strings("paint.title")}
</AppText>
}
/>
);
};
renderAnimal = () => {
return (
<CardView
image={require("../../../../res/images_paint/newPaintingScreen/animals_2x.png")}
styleImg={styles.styleAnimal}
title={strings("paint.animals")}
backgroundColor={"#fff989"}
colorButton={"#FE6230"}
onPress={() =>
NavigationActions.navigate("PaintAnimals", {
studiedNumber: this.state.studiedNumber,
studiedAlphabet: this.state.studiedAlphabet
})
}
/>
);
}
renderObject = () => {
const { studiedAlphabet } = this.state;
return (
<CardView
image={require("../../../../res/images_paint/newPaintingScreen/object_2x.png")}
styleImg={styles.styleObject}
title={strings("paint.objects")}
backgroundColor={"#B29FFF"}
colorButton={"#FE6230"}
onPress={() =>
NavigationActions.navigate("PaintObjects", {
studiedNumber: this.state.studiedNumber,
studiedAlphabet: this.state.studiedAlphabet
})
}
/>
);
}
renderAnimal = () => {
return (
<CardView
image={require("../../../../res/images_paint/newPaintingScreen/animals_2x.png")}
styleImg={styles.styleAnimal}
title={strings("paint.animals")}
backgroundColor={"#fff989"}
colorButton={"#FE6230"}
onPress={() =>
NavigationActions.navigate("PaintAnimals", {
studiedNumber: this.state.studiedNumber,
studiedAlphabet: this.state.studiedAlphabet
})
}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column'
},
containerMio: {
flex: 1,
flexDirection: "column"
},
backgroundImage: {
resizeMode: "stretch",
position: "absolute",
width: "100%",
height: "100%"
},
newPaintImage: {
position: "absolute",
width: "100%",
height: "100%"
},
styleAnimal: {
resizeMode: "center",
width: sizeWidth(70),
height: sizeWidth(50),
marginLeft: sizeWidth(-5),
},
styleObject: {
resizeMode: "center",
width: sizeWidth(70),
height: sizeWidth(50),
marginLeft: sizeWidth(-5),
}
})

React Native (Expo): TouchableOpacity onPress is not a function / is undefined

I was following this tutorial on Linkedin-Learning and suddelny my code wouldn't work anymore.
Unfortunately i don't really understand these error messages:
This warning always appears:
Warning: Failed prop type: The prop onPress is marked as required in
RandomNumber, but its value is undefined.
And if I press one of the "buttons", this error messages comes up:
TypeError: _this.props.onPress is not a function. (In
'_this.props.onPress(_this.props.id)', '_this.props.onPress' is
undefined)
RandomNumber.js:
import React from "react";
import { Text, TouchableOpacity, StyleSheet } from "react-native";
import PropTypes from "prop-types";
class RandomNumber extends React.Component {
static propTypes = {
id: PropTypes.number.isRequired,
number: PropTypes.number.isRequired,
isDisabled: PropTypes.bool.isRequired,
onPress: PropTypes.func.isRequired,
};
handlePress = () => {
if (this.props.isDisabled) {
return;
}
this.props.onPress(this.props.id);
};
render() {
return (
<TouchableOpacity onPress={this.handlePress}>
<Text style={[styles.random, this.props.isDisabled && styles.disabled]}>
{this.props.number}
</Text>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
random: {
backgroundColor: "#999",
width: 120,
marginHorizontal: 15,
marginVertical: 25,
fontSize: 35,
textAlign: "center",
},
disabled: {
opacity: 0.2,
},
});
export default RandomNumber;
Game.js:
import React from "react";
import { View, Text, Button, StyleSheet } from "react-native";
import PropTypes from "prop-types";
import RandomNumber from "./RandomNumber";
import shuffle from "lodash.shuffle";
class Game extends React.Component {
static propTypes = {
randomNumberCount: PropTypes.number.isRequired,
initialSeconds: PropTypes.number.isRequired,
onPlayAgain: PropTypes.func.isRequired,
};
state = { selectedIds: [], remainingSeconds: this.props.initialSeconds };
gameStatus = "PLAYING";
randomNumbers = Array.from({ length: this.props.randomNumberCount }).map(
() => 1 + Math.floor(10 * Math.random())
);
target = this.randomNumbers
.slice(0, this.props.randomNumberCount - 2)
.reduce((acc, curr) => acc + curr, 0);
shuffledRandomNumbers = shuffle(this.randomNumbers);
componentDidMount() {
this.intervalID = setInterval(() => {
this.setState(
(prevState) => {
return { remainingSeconds: prevState.remainingSeconds - 1 };
},
() => {
if (this.state.remainingSeconds === 0) {
clearInterval(this.intervalID);
}
}
);
}, 1000);
}
componentWillUnmount() {
clearInterval(this.intervalID);
}
isNumberSelected = (numberIndex) => {
return this.state.selectedIds.indexOf(numberIndex) >= 0;
};
selectNumber = (numberIndex) => {
this.setState((prevState) => ({
selectedIds: [...prevState.selectedIds, numberIndex],
}));
};
UNSAFE_componentWillUpdate(nextProps, nextState) {
if (
nextState.selectedIds !== this.state.selectedIds ||
nextState.remainingSeconds === 0
) {
this.gameStatus = this.calcGameStatus(nextState);
if (this.gameStatus !== "PLAYING") {
clearInterval(this.intervalID);
}
}
}
calcGameStatus = (nextState) => {
const sumSelected = nextState.selectedIds.reduce((acc, curr) => {
return acc + this.shuffledRandomNumbers[curr];
}, 0);
if (this.state.remainingSeconds === 0) {
return "LOST";
}
if (sumSelected < this.target) {
return "PLAYING";
}
if (sumSelected === this.target) {
return "WON";
}
if (sumSelected > this.target) {
return "LOST";
}
};
render() {
const gameStatus = this.gameStatus;
return (
<View style={styles.container}>
<Text style={[styles.target, styles[`STATUS_${gameStatus}`]]}>
{this.target}
</Text>
<View style={styles.randomContainer}>
{this.shuffledRandomNumbers.map((randomNumber, index) => (
<RandomNumber
key={index}
id={index}
number={randomNumber}
onPress={this.state.selectNumber}
isDisabled={
this.isNumberSelected(index) || gameStatus !== "PLAYING"
}
/>
))}
</View>
{this.gameStatus !== "PLAYING" && (
<Button title="Play Again" onPress={this.props.onPlayAgain} />
)}
<Text>{this.state.remainingSeconds}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#ddd",
flex: 1,
},
target: {
fontSize: 40,
backgroundColor: "#bbb",
margin: 50,
textAlign: "center",
},
randomContainer: {
flex: 1,
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "space-around",
},
STATUS_PLAYING: {
backgroundColor: "#bbb",
},
STATUS_WON: {
backgroundColor: "green",
},
STATUS_LOST: {
backgroundColor: "red",
},
});
export default Game;
App.js:
import React from "react";
import Game from "./Game";
class App extends React.Component {
state = { gameId: 1 };
resetGame = () => {
this.setState((prevState) => {
return { gameId: prevState.gameId + 1 };
});
};
render() {
return (
<Game
key={this.state.gameId}
onPlayAgain={this.resetGame}
randomNumberCount={6}
initialSeconds={10}
/>
);
}
}
export default App;
I've already tried some solutions from other posts, but none of them worked.
Any help is appreciated.

Issue with photos length

I am facing 2 issues related to length of my selected photos:
When selecting photos, it lets me to select 5 photos without any issue (it fits my length restriction), however it doesn't save the chosen photos, when I go to the next screen. In another scenario, when I am at the same screen where I choose photos and I choose 6 photos, it selects the 6 photo but the warning popup will appear and say that its currently supports 5, then when I go to next screen its saves the selected photos unlike previously.
If I deselect photos and then try to select another photos (still in my length limit) popup jumps with selection limit and doesn't let me choose photos, when I go to the next screen it saves the changes from previous selection and not from current one.
import React from 'react';
import {
View,
ScrollView,
Image,
Dimensions,
TextInput,
Text,
StatusBar,
TouchableHighlight,
Linking,
Keyboard,
CameraRoll,
KeyboardAvoidingView
} from 'react-native';
import {connect} from 'react-redux';
import {ActionCreators} from '../redux/actions';
import {bindActionCreators} from 'redux';
import Colors from '../constants/Colors';
import api from '../api';
import {
getEmailAddress,
showError,
renderMessageBar,
registerMessageBar,
unregisterMessageBar
} from '../utils/ComponentUtils';
import {
regularHeader,
mainHeader
} from '../utils/Headers';
import {NavigationActions} from 'react-navigation';
import {SelectionLimitDialog} from '../utils/Dialogs';
import {ifIphoneX, isIphoneX} from 'react-native-iphone-x-helper';
import {SafeAreaView} from 'react-navigation';
// specific component imports.
import {List, ListItem} from 'react-native-elements'
import {Button} from 'react-native-elements'
import Loader from '../components/Loader';
import LoaderError from '../components/LoaderError';
import SelectedPhoto from '../components/SelectedPhoto';
class MultiSafeeScreen extends React.Component
{
static navigationOptions = ({navigation}) => {
const {params} = navigation.state;
const isIncome = params ? params.isIncome : false;
const notificationAction = params ? params.notificationAction : () => {};
const isShowBack = params ? params.isShowBack : false;
return mainHeader({
isShowBack: isShowBack,
backAction: () => navigation.goBack(),
notificationAction: () => notificationAction(),
income: isIncome
});
};
constructor(props) {
super(props);
this.selectedPhotos = [];
this.state = {
photos: null,
loader: {
loading: 0,
message: "Loading photos..."
},
selectedPhotos: [],
supportLength: 5
};
this.props.navigation.setParams({notificationAction: this.onNotification, isIncome: this.props.isNewNotifications});
}
UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.isNewNotifications !== this.props.isNewNotifications) {
this.props.navigation.setParams({notificationAction: this.onNotification, isIncome: newProps.isNewNotifications});
}
}
componentDidMount() {
registerMessageBar(this.refs.alert);
let options = {
first: 30,
assetType: 'Photos',
}
CameraRoll.getPhotos(options)
.then(r => {
this.setState({
photos: r.edges,
loader: {
loading: 1,
message: "Loading photos..."
},
});
})
.catch((err) => {
//Error Loading Images
});
StatusBar.setHidden(false);
}
componentWillUnmount() {
unregisterMessageBar();
this.props.setSelectedPhotos(0);
}
onNotification = () => {
this.props.setNewNotifications(false);
this.props.navigation.navigate("Notifications");
}
closeKeyboard = () => {
Keyboard.dismiss();
}
onSelectPhoto = (photo, index) => {
let photos = new Set([...this.selectedPhotos]);
let len = photos.size + 1 ;
console.log('photos')
if (len > this.state.supportLength) {
this.limitDialog.open();
this.setState({selectedPhotos: this.selectedPhotos});
this.props.setSelectedPhotos(len);
}
else {
photos.add(photo);
this.selectedPhotos = Array.from(photos);
}
}
onDeselectPhoto = (photo, index) => {
let photos = new Set([...this.state.selectedPhotos]);
let len = photos.size - 1;
photos.delete(photo);
this.setState({selectedPhotos: Array.from(photos)});
this.props.setSelectedPhotos(len);
}
onNext = () => {
this.props.navigation.navigate("MultiSafeeCreate", {
isShowBack: true,
selected: [...this.state.selectedPhotos]
});
}
renderLoader() {
let {width, height} = Dimensions.get('window');
let photoWidth = width/3;
if (this.state.loader.loading === 0) {
return <Loader style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
else if (this.state.loader.loading === 2) {
return <LoaderError style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
// if photos are null do nothing, else if empty show onbording
// if has photos show photos.
if (this.state.photos === null) {
return <Loader style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
else {
return (
<View style={{width: width, maxHeight: 600}}>
<ScrollView >
<View style={{flexDirection: 'row', width: width, flexWrap: 'wrap',marginBottom:40, justifyContent: 'space-between'}}>
{
this.state.photos.map((p, i) => {
return (
<SelectedPhoto
key={i}
index={i}
style={{
width: photoWidth,
height: photoWidth,
}}
borderColor = "white"
limit={this.state.supportLength}
photo={p}
onSelectPhoto={this.onSelectPhoto}
onDeselectPhoto={this.onDeselectPhoto}
/>
);
})
}
</View>
</ScrollView>
<View style={{ position:'absolute', right:-15, top:475 }}>
<Button
onPress={this.onNext}
containerViewStyle={{width: width}}
backgroundColor={Colors.red}
title='NEXT' />
</View>
</View>
);
}
}
render() {
return (
<View style={{flex: 1, backgroundColor: Colors.white}}>
{this.renderLoader()}
<SelectionLimitDialog ref={(el) => this.limitDialog = el} />
{renderMessageBar()}
</View>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(ActionCreators, dispatch);
}
function mapStatesToProps(state) {
return {
isNewNotifications: state.isNewNotifications
};
}
export default connect(mapStatesToProps, mapDispatchToProps)(MultiSafeeScreen);

React Native: React Navigation StackNavigator not working. Getting error: “undefined is not an object (evaluating '_this3.props.navigation.navigate')”

I'm facing one issue I have simple and usual navigation flow with Stacknavigation and once they login they will see the Tab navigation.
In tab navigation I have chat screen which will render segments in one screen, each segment will produce a list of chat heads which is supposed to be open in the individual chat screen.
Chatscreen.js
import React, { Component } from "react";
import {
View,
Text,
StyleSheet
} from "react-native";
import AdminChat from './Chat/AdminChat';
import AcademicChat from './Chat/AcademicChat';
import ActiveChat from './Chat/ActiveChat';
import { createMaterialTopTabNavigator } from 'react-navigation';
import Icon from 'react-native-vector-icons/Ionicons';
import { Button, Container, Content, Header, Body, Left, Right, Title } from 'native-base';
class ChatScreen extends Component{
state = {
activeIndex : 0
}
segmentClicked = (index) => {
this.setState({activeIndex: index})
}
renderSection = () => {
if (this.state.activeIndex === 0) {
return <AdminChat />
} else if (this.state.activeIndex === 1) {
return <AcademicChat />
} else {
return <ActiveChat />
}
}
render(){
return (
<Container>
<Header style={{backgroundColor: '#8E44AD'}}>
<Left>
</Left>
<Body>
<Title style={{color: 'white'}}>Chat</Title>
</Body>
<Right />
</Header>
<View style={styles.container}>
<View style={{flexDirection: 'row', justifyContent: 'space-around', borderBottomWidth: 1, borderBottomColor: 'grey' }}>
<Button
transparent
onPress={()=>{this.segmentClicked(0)}}
active={this.state.activeIndex === 0}>
<Text style={[this.state.activeIndex === 0 ? { color: '#8E44AD' } : {color: 'grey'}]}>Admin</Text>
</Button>
<Button
transparent
onPress={()=>{this.segmentClicked(1)}}
active={this.state.activeIndex === 1}>
<Text style={[this.state.activeIndex === 1 ? { color: '#8E44AD' } : {color: 'grey'}]}>Academic</Text>
</Button>
<Button
transparent
onPress={()=>{this.segmentClicked(2)}}
active={this.state.activeIndex === 2}>
<Text style={[this.state.activeIndex === 2 ? { color: '#8E44AD' } : {color: 'grey'}]}>Chat</Text>
</Button>
</View>
{this.renderSection()}
</View>
</Container>
);
}
}
export default ChatScreen;
from above code, I have generated Chat Screen, which is a part of tab navigator, and in that I am loading the AdminScreen.js.
import React, { Component } from "react";
import { View, Text, FlatList, ActivityIndicator, StyleSheet } from "react-native";
import { List, ListItem, SearchBar } from "react-native-elements";
import axios from 'axios';
class AdminChat extends Component{
state = {
adminChat : [],
userid: "2980",
usertype: '1'
}
componentWillMount = async () => {
console.log(this.state.userid)
try {
let { data } = await axios
.post("https://tgesconnect.org/api/Communication_group", {
userid: this.state.userid,
group_id: '0',
is_sub_group: '0',
usertype: this.state.usertype,
})
.then(response => {
//console.log(response.data.data.group_list);
if (response.data.status === "success") {
//console.log("Success")
this.setState({
adminChat: response.data.data.group_list,
});
} else {
alert("Something went wrong");
}
});
} catch (err) {
console.log(err);
}
//console.log(this.state.adminChat.group_name[0])
};
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "100%",
backgroundColor: "#CED0CE",
}}
/>
);
};
render () {
return (
<List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0 }}>
<FlatList
data={this.state.adminChat}
renderItem={({ item }) => (
<ListItem
// roundAvatar
title={item.group_name}
// subtitle={item.email}
// avatar={{ uri: item.picture.thumbnail }}
containerStyle={{ borderBottomWidth: 0 }}
onPress={()=>this.props.navigation.push('onescreen')}
/>
)}
keyExtractor={item => item.group_id}
ItemSeparatorComponent={this.renderSeparator}
/>
</List>
)
}
}
export default AdminChat;
const styles = StyleSheet.create({
container:{
flex:1,
alignItems:'center',
justifyContent:'center'
}
});
Now if I click to open a single List item and use this.props.navigation.navigate('adminSingle.js') it is not working, how can I solve it?
I am using "react-navigation": "^2.6.0"
Looks like you forgot to pass navigation as prop for AdminScreen
renderSection = () => {
if (this.state.activeIndex === 0) {
return <AdminChat navigation={this.props.navigation}/>
} else if (this.state.activeIndex === 1) {
return <AcademicChat />
} else {
return <ActiveChat />
}
}

Categories