Passing props to child doesn't make him update - React Native - reactjs

I am writing because I can't figure why one of the two childs Graph.js won't update after I udpate the state of the parent Data.js (throught a "lift up" via the second child Bouton.js).
I feel giga dumb and it's been now hours, I'm desperate...
I am trying to display charts with buttons above to choose a period of time for the chart (day, week, month). Clicking the button can change the state of the parent but I can't make the child Graph to update. I know I am doing something wrong.
Parent: Data.js
export default class Data extends React.Component {
constructor(props) {
super(props);
this.state = { periode: "Jour" };
}
handleClick(p) {
this.setState({
periode: p
});
}
render() {
console.log(this.state);
return (
<View>
<Boutons
onClick={res => this.handleClick(res)}
cursor={this.state.periode}
/>
<Graph periode={this.state.periode} dataType="temp" />
<Graph periode={this.state.periode} dataType="press" />
</View>
);
}
}
Child 1 (everything seems fine)
export default class Boutons extends React.Component {
constructor(props) {
super(props);
}
_getNextEntryTime() {
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
var res;
if (m >= 30) {
res = (h + 1).toString() + ":00";
} else {
res = h.toString() + ":30";
}
return res;
}
//Gestion de la selection des boutons
_boutonStyle(periode) {
if (this.props.cursor == periode) {
return {
// backgroundColor: "#9c9c9c",
borderBottomWidth: 3,
borderColor: "#728FB5",
width: Dimensions.get("window").width / 3 - 10,
height: 30,
alignItems: "center",
justifyContent: "center"
};
} else {
return {
backgroundColor: "#dfdfdf",
width: Dimensions.get("window").width / 3 - 10,
height: 30,
borderRadius: 2,
alignItems: "center",
justifyContent: "center"
};
}
}
_textStyle(periode) {
if (this.props.cursor == periode) {
return { color: "#728FB5" };
} else {
return { color: "black" };
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.container_top}>
<View style={styles.rect}>
<Text style={styles.text_top}>
Prochain relevé: {`\n`}
<Text style={styles.numbers}>{this._getNextEntryTime()}</Text>
</Text>
</View>
<Single />
</View>
<View style={styles.container_buttons}>
<TouchableOpacity
style={this._boutonStyle("Jour")}
onPress={() => this.props.onClick("Jour")}
>
<Text style={this._textStyle("Jour")}>Jour</Text>
</TouchableOpacity>
<TouchableOpacity
style={this._boutonStyle("Semaine")}
onPress={() => this.props.onClick("Semaine")}
>
<Text style={this._textStyle("Semaine")}>Semaine</Text>
</TouchableOpacity>
<TouchableOpacity
style={this._boutonStyle("Mois")}
onPress={() => this.props.onClick("Mois")}
>
<Text style={this._textStyle("Mois")}>Mois</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
Graph.js Child 2 that won't update, nothing is happening
class Graph extends React.Component {
constructor(props) {
super(props);
this.state = { isLoading: true, data: [], format_const: null };
}
// Chargement de la page et recherche des entrys
componentDidMount() {
const entrys = getEntry(this.props.periode);
entrys.then(reponse => {
reponse.map(donnee => {
this.setState({
data: this.state.data.concat(donnee[this.props.dataType])
});
});
this.setState({
format_const: Config.CHART[this.props.dataType],
isLoading: false
});
});
}
// Affichage du loading
_displayLoading() {
if (this.state.isLoading) {
return (
<View style={styles.loading_container}>
<ActivityIndicator size="large" />
</View>
);
}
}
_displayChart() {
return (
<LineChart
data={{
datasets: [
{
data: this.state.data,
strokeWidth: 2 // optional
}
],
legend: [this.state.format_const["label"]]
}}
width={Dimensions.get("window").width - 10} // from react-native
height={220}
withInnerLines={false}
yAxisSuffix={this.state.format_const["alert"]}
onDataPointClick={({ value, dataset, getColor }) =>
Alert.alert(`${value}` + this.state.format_const["alert"])
}
chartConfig={{
backgroundGradientFrom: this.state.format_const["color"],
backgroundGradientTo: this.state.format_const["color"],
decimalPlaces: 0, // optional, defaults to 2dp
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
style: {
borderRadius: 16
},
propsForDots: {
r: "2"
}
}}
bezier
style={{
marginVertical: 10,
borderRadius: 16
}}
/>
);
}
render() {
if (!this.state.isLoading) {
return <View>{this._displayChart()}</View>;
} else {
return <View>{this._displayLoading()}</View>;
}
}
}

It appears that your only use of the prop periode is in the componentDidMount method of Graph. So at mount time, Graph reads what the prop is, and then sets the state, which is used in the Graph render method. But when the parent component changes its state, and the new value for this.state.periode is passed as a prop to Graph, Graph doesnt doesn't necessarily know what to do with this updated information. So you'll need to use a componentDidUpdate statement to read new props coming in from the parent's state:
componentDidUpdate(prevProps){
if (prevProps.periode !== this.props.periode){
const entrys = getEntry(this.props.periode);
entrys.then(reponse => {
reponse.map(donnee => {
this.setState({
data: this.state.data.concat(donnee[this.props.dataType])
});
});
});
}
}
I'm assuming you want the same thing to happen in `componentDidMount` as is happening in `componentDidUpdate`, but you may need to change the code within `componentDidUpdate` to whatever you need.

Related

set Multiple state Id for custom component in React Native

I have implemented custom inputBox component. So When I am using this component first time then it is working fine and when I am using multiple time in one page then data is prepopulate to next component.
Custom component:
import React, { createRef } from 'react';
import {
View,
TextInput,
Alert,
Text,
StyleSheet
} from "react-native";
class BoxInput extends React.Component {
constructor(props) {
super(props)
this.state = {
digit1: '',
digit2: '',
digit3: '',
...props
}
this.digit1Ref = createRef()
this.digit2Ref = createRef()
this.digit3Ref = createRef()
}
componentDidMount() {
this.digit1Ref.current.focus()
}
componentDidUpdate(prevProps) {
if (this.state.digit1 && this.state.digit2 &&
this.state.digit3
}
saveText(text, key) {
this.setState({ ...this.state, [key]: text }, () => {
if (text) {
key == 'digit1' ? this.digit2Ref.current.focus() : null
key == 'digit2' ? this.digit3Ref.current.focus() : null
key == 'digit3'
}
const boxInputValue = this.state.digit1 + this.state.digit2 + this.state.digit3
this.props.onBoxInput(boxInputValue)
});
}
render() {
return (
<>
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit1Ref} style={styles.boxStyle} value={this.state.digit1} onChangeText={(text) => this.saveText(text, 'digit1')} />
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit2Ref} style={styles.boxStyle} value={this.state.digit2} onChangeText={(text) => this.saveText(text, 'digit2')} />
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit3Ref} style={styles.boxStyle} value={this.state.digit3} onChangeText={(text) => this.saveText(text, 'digit3')} />
</>
)
}
}
const styles = StyleSheet.create({
boxStyle: {
marginTop: 20,
height: 57,
width: 50,
borderRadius: 10,
borderWidth: 1,
borderColor: '#F1F5F9',
backgroundColor: '#F1F5F9',
fontSize: 20,
lineHeight: 40,
paddingHorizontal: 15,
textAlign: 'center'
}
})
export default BoxInput;
import React, { createRef } from 'react';
import styles from './style';
import {
View,
TextInput,
Alert
} from "react-native";
import { connect } from "react-redux";
import * as Animatable from 'react-native-animatable';
import BoxInput from "../../../../md-components/atoms/boxinput"
class MPINScreen extends React.Component {
constructor(props) {
super(props)
this.state = {
confirmMpinEnable: true,
...props
}
this.codes = [{
value: '+91',
}]
}
componentDidUpdate(prevProps) {
if (this.state.mpinValue.split("").length == 3 &&
prevProps.success_msg != this.props.success_msg && this.props.success_msg == 'verified') {
NavigationService.navigate(this.props.navigation, 'MPINVerifyOnboarding')
}
}
handleSubmit = () => {
if (this.state.mpinValue != this.state.confirmMpinValue) {
Alert.alert(
"Error",
"MPIN is not machted",
[
{ text: "OK" }
],
{ cancelable: false }
);
} else {
this.props.verifyMpin({
"mpin": this.state.mpinValue,
phoneNumber: this.props.mobileNumber
})
}
}
mpinConfirmation = () => {
if (this.state.mpinValue.split("").length != 6) {
Alert.alert(
"Error",
"Please insert 6 digit mpin",
[
{ text: "OK" }
],
{ cancelable: false }
);
}else{
this.setState({
confirmMpinEnable: false,
});
}
}
mpinText = (args) => {
this.setState({
mpinValue: args,
});
}
confirmMpinText = (args) => {
this.setState({
confirmMpinValue: args,
});
}
render() {
return (
<>
<HeaderComponent backgroundColor="#E5E5E5" showLeftIcon={true} showRightIcon={false} />
<View style={styles.container}>
<Text style={[styles.textInfo, styles.textTitle]}>We are almost there!</Text>
<View style={styles.imageWrapper}>
<Animatable.View animation="slideInDown" iterationCount={1} style={styles.centerIconWrap}>
<Image style={styles.centerIcon} source={mpin_card} />
</Animatable.View>
</View>
{this.state.confirmMpinEnable ?
<Text style={[styles.textInfo]}>Setup your MPIN</Text> : <Text style={[styles.textInfo]}>Confirm your MPIN</Text>
}
{this.state.confirmMpinEnable ?
<View style={styles.rowWrap}>
<BoxInput id="catFood1" onBoxInput={this.mpinText} />
</View>:
<View style={styles.rowWrap}>
<BoxInput id="catFood2" onBoxInput={this.confirmMpinText} />
</View>
}
<View style={styles.marginBottom}>
<Text style={[styles.mpinNote]}>M-PIN is a short 6-digit PIN that you have to set for</Text>
<Text style={[styles.mpinNote]}>our mandatory Two-Factor Authentication</Text>
</View>
<View style={styles.bottomBtnSyle}>
<View style={styles.multipleBtnStyle}>
<Button onPress={this.handleBack}>{"Back"}</Button>
</View>
{this.state.confirmMpinEnable ?
<View style={styles.multipleBtnStyle}>
<Button onPress={this.mpinConfirmation} >{"Confirm"}</Button>
</View> :
<View style={styles.multipleBtnStyle}>
<Button onPress={this.handleSubmit} >{"Save & Continue"}</Button>
</View>
}
</View>
</View>
</>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MPINScreen);
when I am click on confirm button then hide and display . But in second component data is prepopulating which i was inserted.
in this screen shot data is prepopulate but i want this empty, Because user has to insert again. but it is taking same value from previous state. how we can use multiple time same component in one page.
General idea:
Create a property in MPINScreen state that is changing (incrementing) every attempt (you can call it attempt) and pass it as prop to BoxInput.
In BoxInput create a reset function (that will clean the values of the text inputs and focus the first input). On componentDidUpdate check if attempt prop changed. If true - save the new value in BoxInput state and call "reset".

React Native Expo AV - Implementing SeekBar

I am attempting to use react-native-slider with Expo AV to create a seekbar, but am having trouble updating the 'value' state of slider. When I try to set it to currentPosition/durationPosition, it errors out, likely because initially these values are NaN. I CAN display current/duration however.
My best guess is that I need a way to wait until my mp3 is loaded before rendering the SeekBar. I probably also need to do a better job of separating components and keep PlayerScreen very minimal. I've messed around with this code so much I can barely remember what I've tried... Getting close to ditching Expo because react-native-track-player looks easier to work with and I've heard some bad things about Expo. Anyways, here's where I'm at now
export default class PlayerScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
isPlaying: false,
playbackObject: null,
volume: 1.0,
isBuffering: false,
paused: true,
currentIndex: 0,
durationMillis: 1,
positionMillis:0,
sliderValue:0,
isSeeking:false,
}
}
async componentDidMount() {
try {
await Audio.setAudioModeAsync({
allowsRecordingIOS: false,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
playsInSilentModeIOS: true,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DUCK_OTHERS,
shouldDuckAndroid: true,
staysActiveInBackground: true,
playThroughEarpieceAndroid: true
})
this.loadAudio()
} catch (e) {
console.log(e)
}
}
async loadAudio() {
const { currentIndex, isPlaying, volume} = this.state
try {
const playbackObject = new Audio.Sound()
const source = {
uri: this.props.route.params.item.uri
}
const status = {
shouldPlay: isPlaying,
volume,
}
playbackObject.setOnPlaybackStatusUpdate(this.onPlaybackStatusUpdate)
await playbackObject.loadAsync(source, status, true)
this.setState({playbackObject})
var sliderValue = this.state.positionMillis/this.state.durationMillis
} catch (e) {
console.log(e)
}
}
handlePlayPause = async () => {
const { isPlaying, playbackObject } = this.state
isPlaying ? await playbackObject.pauseAsync() : await playbackObject.playAsync()
this.setState({
isPlaying: !isPlaying
})
}
onPlaybackStatusUpdate = status => {
this.setState({
isBuffering: status.isBuffering,
durationMillis: status.durationMillis,
positionMillis: status.positionMillis,
})
}
render() {
const { item } = this.props.route.params;
return (
<View style={globalStyles.container}>
<Header />
<View style={globalStyles.subHeader}>
<Text style={globalStyles.title}>{ item.title }</Text>
</View>
<View style={styles.text}>
<Text>{ item.text }</Text>
</View>
<SeekBar
durationMillis={this.state.durationMillis}
positionMillis={this.state.positionMillis}
sliderValue={this.state.sliderValue}
/>
And here's the SeekBar component:
const SeekBar = ({
positionMillis,
durationMillis,
sliderValue
}) => {
return (
<View style={styles.container}>
<View style={{ flexDirection: 'row' }}>
<View style={{ flex: 1 }} />
<Text style={[styles.text, { width: 40 }]}>
{positionMillis + ' / ' + durationMillis}
</Text>
</View>
<Slider
minimumValue={0}
maximumValue={1}
value={sliderValue}
style={styles.slider}
minimumTrackTintColor='#fff'
maximumTrackTintColor='rgba(255, 255, 255, 0.14)'
/>
</View>
);
};
export default SeekBar;
put
<SeekBar
durationMillis={this.state.durationMillis}
positionMillis={this.state.positionMillis}
sliderValue={this.state.sliderValue}
/>
in the screen component and
const SeekBar = ({
positionMillis,
durationMillis,
sliderValue
}) => {
sliderValue = positionMillis/durationMillis
return (
<View style={styles.container}>
<View style={{ flexDirection: 'row' }}>
<View style={{ flex: 1 }} />
in the SeekBar component

react native multiple video with Swiper component play pause issue

I have multiple videos in the swiper to show videos one by one, but all the videos are loaded and playing at the same time and audios are messed up, I want current video only play at a time.
import * as React from 'react';
import { Text, View, StyleSheet,Image, Dimensions } from 'react-native';
import { Constants } from 'expo';
import { Video } from 'expo';
import Swiper from './Swiper';
import InViewPort from './InViewport';
const screenWidth = Dimensions.get('window').width ;
const screenHeight = Dimensions.get('window').height;
export default class App extends React.Component {
constructor(props) {
super(props);
// Your source data
this.state = {
images: {},
muted : false,
paused: true,
};
this.player = Array();
this.onChangeImage = this.onChangeImage.bind(this);
}
videoError(err){
console.warn(err);
}
pauseVideo = () => {
var curr = this.state.currentIndex;
console.warn(curr);
if(this.player[curr]) {
this.setState({paused: true });
}
}
playVideo = () => {
var curr = this.state.currentIndex;
console.warn(curr);
if(this.player[curr]) {
this.setState({paused: false});
}
}
handlePlaying = (isVisible) => {
isVisible ? this.playVideo() : this.pauseVideo();
}
onChangeImage (index) {
this.setState({ currentIndex: index});
}
render() {
let items = Array.apply(null, Array(15)).map((v, i) => {
return {
id: i,
caption: i + 1,
source: { uri: 'http://placehold.it/200x200?text=' + (i + 1) },
dimension: '{ width: 150, height: 150 }',
};
});
return(
<View style={styles.DefaultView}>
<Swiper
showsPagination={false}
onIndexChanged={this.onChangeImage}
index={0}
>
{items.map((item, key) => {
if(key==1 || key ==5){
return (
<InViewPort onChange={this.handlePlaying} key={key}>
<Video onError={this.videoError}
muted={this.state.muted}
paused={this.state.paused}
source={{uri: 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4' }}
style={styles.backgroundVideo}
ref={(ref) => {
this.player[key] = ref;
}}
controls={true}
/>
</InViewPort>
)
}else{
return(
<Image
resizeMode='contain'
style={{width:screenWidth, height: screenHeight}}
source={item.source}
key={key}
/>
)
}
})}
</Swiper>
</View>
)
}
}
const styles = StyleSheet.create({
scrollView: {
flex: 1,
flexDirection: 'row',
},
DefaultView: {
flex: 1,
backgroundColor: '#000',
width: screenWidth,
justifyContent:'center',
alignItems:'center'
},
iconContainer: {
flexDirection: "row",
justifyContent: "space-evenly",
width: 150,
},
backgroundVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
width: screenWidth,
height: 300,
marginTop:'50%',
position:'absolute',
},
});
I need some idea on this, we have a player reference to be used, also swiper component have onIndexChanged which will trigger when we moved to next video, how we can link the reference of the player to onIndexChanged and when we do swipe how we make it current video only to play?
As per Andrew suggestion I have used InPortView component too determine the current view of swipe, but still I am not sure how to make reference for video elements to be used in the functions for play and pause the concern video.
Components used:
For video react-native-video
For Swiper : react-native-swiper
Updated Full code with Expo example : Expo Snack
So taking your snack. I managed to get it to work.
I moved the Video out into its own component and passed a few additional props to it, the index in the array and the currentIndex showing.
export default class App extends React.Component {
constructor(props) {
super(props);
// Your source data
this.state = {
images: {},
muted : false,
paused: true,
currentIndex: 0
};
}
onChangeImage = (index) => {
console.log('currentIndex ', index)
this.setState({ currentIndex: index});
}
render() {
let items = Array.apply(null, Array(15)).map((v, i) => {
return {
id: i,
caption: i + 1,
source: { uri: 'http://placehold.it/200x200?text=' + (i + 1) },
dimension: '{ width: 150, height: 150 }',
};
});
return(
<View style={styles.DefaultView}>
<Swiper
showsPagination={false}
onIndexChanged={this.onChangeImage}
index={0}
>
{items.map((item, key) => {
if(key==1 || key ==5){
return (
<VideoPlayer key={key} index={key} currentIndex={this.state.currentIndex}/>
)
}else{
return(
<Image
resizeMode='contain'
style={{width:screenWidth, height: screenHeight}}
source={item.source}
key={key}
/>
)
}
})}
</Swiper>
</View>
)
}
}
The video component uses react-native-inviewport to help handle whether or not it is in the viewport. However it doesn't play nicely with react-native-swiper but it is possible to get it to work.
export default class VideoPlayer extends React.Component {
pauseVideo = () => {
if(this.video) {
this.video.pauseAsync();
}
}
playVideo = () => {
if(this.video) {
this.video.playAsync();
}
}
handlePlaying = (isVisible) => {
this.props.index === this.props.currentIndex ? this.playVideo() : this.pauseVideo();
}
render() {
return (
<View style={styles.container}>
<InViewPort onChange={this.handlePlaying}>
<Video
ref={ref => {this.video = ref}}
source={{ uri: 'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4' }}
rate={1.0}
volume={1.0}
isMuted={false}
resizeMode="cover"
shouldPlay
style={{ width: WIDTH, height: 300 }}
/>
</InViewPort>
</View>
)
}
}
When I used the InViewPort component alone it seemed to think that the video in position 6 was in the viewport and would play it. So what I use the InviewPort is to perform a check to compare the index of the video with the currentIndex if they match play the video otherwise pause. I suppose this could be updated to use componentDidUpdate to handle the changes in the props. However, additional checks will need to be performed when the component mounts so that it doesn't play the video.
Here is my snack with it working. https://snack.expo.io/#andypandy/swiper-video

action is being dispatched before the state updates

After authentication I am redirected to the dashboard page where I call 3 APIs as soon as I land and then I display the data on it. I am getting the siteId from authentication page and is available in redux store and set that siteId to dashboard page's state. The issue is my action is firing before my state gets the value from redux. MapStateToProps is firing the action with undefined. After the action is fired, the state is being set. If I hard code the state, it works. I tried to check if my state is set before the action is fired, but seems like my check is not working.
class Dashboard extends Component {
constructor(props) {
super(props)
this.state = {
alarmCount: [],
workOrderCount: [],
etaWorkOrder: [],
countNum: true,
siteId: this.props.storeNum && this.props.storeNum.siteId
// siteId: 5260
}
}
componentDidMount() {
this.props.getOpenWorkOrdersCount();
this.props.getEtaWorkOrder();
}
componentWillReceiveProps({ alarmCount, workOrderCount, etaWO, storeNum }) {
if(alarmCount.code) {
this.setState({ alarmCount: alarmCount.code.data.ticketCount })
}
if(workOrderCount) {
this.setState({ workOrderCount: workOrderCount.data.event.woOutstanding })
}
if(etaWO) {
this.setState({ etaWorkOrder: etaWO.data.woList })
}
if(storeNum && storeNum.siteId && !(alarmCount.fetching || alarmCount.success) && !this.state.alarmCount.length){
this.props.getAlarmCount({siteId: storeNum.siteId});
}
}
const mapStateToProps = state => {
return {
alarmCount: state.alarmCount,
workOrderCount: state.workOrderCount.count,
etaWO: state.etaWorkOrder.count,
storeNum: state.ssoReducer.user
}
}
const mapDispatchToProps = dispatch => ({
getAlarmCount: data => dispatch(AlarmCountActions.getAlarmCount({ data }))
});
export default connect( mapStateToProps, mapDispatchToProps)(Dashboard);
This is the full component code:
class Dashboard extends Component {
constructor(props) {
super(props)
this.state = {
alarmCount: [],
workOrderCount: [],
etaWorkOrder: [],
countNum: true,
// siteId: props.storeNum && props.storeNum.siteId
siteId: ''
}
console.log('<<< storeNum', props.storeNum);
}
componentDidMount() {
// this.props.getOpenWorkOrdersCount();
// this.props.getEtaWorkOrder();
// if(this.props.storeNum){
// this.props.getAlarmCount(this.props.storeNum.siteId);
// }
}
// componentWillReceiveProps({ alarmCount, workOrderCount, etaWO, storeNum }) {
// if(alarmCount.code) {
// this.setState({ alarmCount: alarmCount.code.data.ticketCount })
// }
// if(workOrderCount) {
// this.setState({ workOrderCount: workOrderCount.data.event.woOutstanding })
// }
// if(etaWO) {
// this.setState({ etaWorkOrder: etaWO.data.woList })
// }
// if(storeNum){
// this.setState({ siteId: storeNum.siteId })
// }
// }
componentDidUpdate(prevProps) {
console.log('prevProps: ', prevProps)
if(prevProps.storeNum.siteId !== this.props.storeNum.siteId){
this.props.getAlarmCount(this.props.storeNum.siteId);
}
}
todaysDateFormatted = () => {
let today = new Date();
let dd = today.getDate();
let mm = today.getMonth() + 1;
let yyyy = today.getFullYear();
if (dd < 10) { dd = '0' + dd }
if (mm < 10) { mm = '0' + mm }
return today = mm + '-' + dd + '-' + yyyy;
}
howManyToday = data => {
let count = 0;
let todaysDate = this.todaysDateFormatted();
data.map(item => {
date = item.eta.replace(/(\d{4})\-(\d{2})\-(\d{2}).*/, '$2-$3-$1')
if(todaysDate == date) count++;
})
return count;
}
render() {
const navigation = this.props.navigation;
const woCount = this.state.workOrderCount
console.log(' ^^^^^^^ storeNuM: ', this.state.siteId)
return (
<View style={styles.container}>
<View style={styles.innerBox}>
<View style={styles.leftBox}>
<TouchableOpacity
style={styles.activeAlarms}
onPress={() => navigation.navigate(routes.ALARMS)}>
<View style={{ justifyContent: 'flex-end', flex: 1, background: 'transparent'}}>
{this.state.countNum ? (
<Fragment>
<Text style={[styles.blueColor, styles.font_24, ]}>{this.state.alarmCount}</Text>
</Fragment>
) : null}
<Text style={[styles.blueColor, styles.font_16] }>Active Alarms</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
style={styles.openWorkOrders}
onPress={() => navigation.navigate(routes.WORK_ORDERS)}>
<View style={{ justifyContent: 'flex-end', flex: 1 }}>
<Text style={[styles.whiteColor, styles.font_24]}>{woCount}</Text>
<Text style={[styles.whiteColor, styles.font_16]}>Open{'\n'}Work Orders</Text>
</View>
</TouchableOpacity>
</View>
<View style={styles.rightBox}>
<TouchableOpacity
style={styles.todayWorkOrders}
onPress={() => navigation.navigate(routes.WORK_ORDERS)}
>
<View style={{ justifyContent: 'flex-end', flex: 1 }}>
<Text style={[styles.whiteColor, styles.font_24]}>{this.howManyToday(this.state.etaWorkOrder)}</Text>
<Text style={[styles.whiteColor, styles.font_16]}>Today ETA{'\n'}Work Orders</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
style={styles.diyTrainingVideos}
onPress={() => navigation.navigate(routes.TRAINING_VIDEOS)}
>
<View style={{ justifyContent: 'flex-end', flex: 1 }}>
<Text style={[styles.blueColor, styles.font_16]}>DIY{'\n'}Training Videos</Text>
</View>
</TouchableOpacity>
</View>
</View>
<View style={styles.createWorkOrderBox}>
<TouchableOpacity
style={styles.createBtn}
onPress={() => navigation.navigate(routes.CREATE_WORK_ORDER)}>
<Text style={styles.workOrderText}>+ WORK ORDER</Text>
</TouchableOpacity>
</View>
</View>
)
}
}
const mapStateToProps = state => {
return {
alarmCount: state.alarmCount,
workOrderCount: state.workOrderCount.count,
etaWO: state.etaWorkOrder.count,
storeNum: state.ssoReducer.user
}
}
const mapDispatchToProps = dispatch => ({
getEtaWorkOrder: () => dispatch(etaWorkOrderActions.etaWorkOrder()),
getOpenWorkOrdersCount: () => dispatch(WorkOrderCountActions.count()),
getAlarmCount: data => dispatch(AlarmCountActions.getAlarmCount({ data })),
logoutUser: () => dispatch(logoutAction.logoutUser())
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(Dashboard);
What is wrong with my check? ComponentWillReceiveProps is firing the action now, I had ComponentDidMount fire the action before, that did not work either. How can I make sure that my state is set before this.props.getAlarmCount({siteId: storeNum.siteId}) is fired?

accessing the state outside the class - Reactnative - this.setState is not a function

I am using custom floating text labels which are outside the class and I want to set the state within it. how can I do it please
I have two floating text fields when I click the button I want to set the state to the entered values in the input text field.
The error is get is
this.setState is not a function
const TextfieldWithFloatingLabel_Card = MKTextField.textfieldWithFloatingLabel()
.withPlaceholder(strings.nineDigitCardNumber)
.withStyle(styles.textfieldWithFloatingLabel)
.withTextInputStyle({ flex: 1 })
.withFloatingLabelFont({
fontSize: 12,
fontWeight: '200',
color: colors.primaryColor
})
.withKeyboardType('numeric')
.withOnEndEditing(e => {
this.setState({ cardDigits: e.nativeEvent.text });
console.log('EndEditing', e.nativeEvent.text);
})
.build();
const TextfieldWithFloatingLabel_NationalId = MKTextField.textfieldWithFloatingLabel()
.withPlaceholder(strings.nationalIdNumber)
.withStyle(styles.textfieldWithFloatingLabel)
.withTextInputStyle({ flex: 1 })
.withFloatingLabelFont({
fontSize: 12,
fontWeight: '200',
color: colors.primaryColor
})
.withKeyboardType('numeric')
.withOnEndEditing(e => {
this.setState({ nationalIdNumber: e.nativeEvent.text });
console.log('EndEditing', e.nativeEvent.text);
})
.build();
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
cardDigits: '',
IdNumber: ''
};
}
render() {
//console.log('rovers - ' + JSON.stringify(this.state.rovers))
return (
<ScrollView style={styles.mainContainer}>
<TextfieldWithFloatingLabel_Card ref="tiNumber" />
<TextfieldWithFloatingLabel_NationalId ref="tiNationalId" />
<TouchableOpacity
title="Transactions"
style={{
height: 60,
backgroundColor: '#673fb4',
marginTop: 20,
alignItems: 'center',
justifyContent: 'center'
}}
onPress={() => {
consoleLog(
'cardnum : ' +
this.state.cardDigits +
' national id - ' +
this.state.IdNumber
);
}}
>
<CommonText style={{ color: 'white' }}>
{strings.signInLower}
</CommonText>
</TouchableOpacity>
</ScrollView>
);
}
}
Thanks
R
Change
TextfieldWithFloatingLabel_Card
To a function instead of a variable and wherever you call TextfieldWithFloatingLabel_Card in the component pass this as a parameter to it so that when you do setState it will work
I will give you hint on how to do
Test.js
const test = this = {
this.setState({test: “working”});
}
export = test();
App.js component
import { test } from “./Test”;
callTest = () => {
test(this);
}
render(){
return(
<div onClick={this.callTest}>
</div>
)
}
So the point here is you need to pass component this to imported regular functions so that you can set the state of the component.
What you doing is old methodology. I would recommend you to handle the event handler functions with in components.
Please execuse me if there are any typo errors because I am answering on my mobile

Resources