How to modify a component's property in a function? - react-native

I'm trying to learn react and how to use third party components, what I'm trying to do now is to use the component that I installed from https://www.npmjs.com/package/react-native-countdown-component
objective:
The Countdown component has a "Props" called "running" which I would like to modify when I "click" on the component.
code:
the code that I'm using is just a fresh new app created using "expo init MyApp", then I've pasted in the code to import and generate the component
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
// https://www.npmjs.com/package/react-native-countdown-component
import CountDown from 'react-native-countdown-component';
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<CountDown
until={60}
size={30}
//onFinish={() => alert('Finished')}
digitStyle={{backgroundColor: '#FFF'}}
digitTxtStyle={{color: '#1CC625'}}
timeToShow={['M', 'S']}
timeLabels={{m: '', s: ''}}
showSeparator={true}
onPress={() =>
{
this.setState({running:true});
}}
running={false}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
what is the correct way to modify the "running" property of the Countdown component when the component is clicked?

You can start using state properly. For this time I will use React Hooks, it's simpler than using the traditional functional or class components. See more
Every time state is updated, it will cause component to rerender with the new value.
import React, { useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
// https://www.npmjs.com/package/react-native-countdown-component
import CountDown from 'react-native-countdown-component';
export default function App() {
const [isRunning, setRunning] = useState(false) //React Hooks
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<CountDown
until={60}
size={30}
//onFinish={() => alert('Finished')}
digitStyle={{backgroundColor: '#FFF'}}
digitTxtStyle={{color: '#1CC625'}}
timeToShow={['M', 'S']}
timeLabels={{m: '', s: ''}}
showSeparator={true}
//When component is pressed, updates state to true
onPress={() => { setRunning(true); }}
running={isRunning}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});

I found another way, that requires a new class but I prefer Ian Steban Vasco's answer.
the solution that I found out was to create a new component that will hold the "state" for the Countdown component, then use the MyCountdown component in the main method instead of directly using the Countdown component
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
// https://www.npmjs.com/package/react-native-countdown-component
import CountDown from 'react-native-countdown-component';
export default class MyCountdown extends React.Component{
state = {
running: false
};
handleOnPress = () =>{
this.setState({running:!this.state.running});
}
render(){
return (
<CountDown
until={60}
size={30}
//onFinish={() => alert('Finished')}
digitStyle={{backgroundColor: '#FFF'}}
digitTxtStyle={{color: '#1CC625'}}
timeToShow={['M', 'S']}
timeLabels={{m: '', s: ''}}
showSeparator={true}
onPress={this.handleOnPress}
running={this.state.running}
/>
);
}
}

Related

Why is MyContext.Provider not showing value in render?

I am a newbie trying to work with react native context. A very simple program, but unable to show the value.
Here is the code:
import React, {Component} from 'react';
import {Text, View } from 'react-native';
export const MyContext = React.createContext();
export default class App extends Component {
static contextType = MyContext;
render() {
this.state = 1
return (
<View>
<Text> Hello There </Text>
<MyContext.Provider value={this.state}>
{this.props.children}
</MyContext.Provider>
</View>
);
};
};
'Hello There' gets displayed. Even if I hard-code the value for MyContext.Provider , it doesn't display anything, and there are no errors either. What am I doing wrong?
Here is an sample with a class component.
You have to create a context React.createContext
You have to apply your context with MyContext.Provider
You have to consume your context with MyContext.Consumer
import { Text, View } from 'react-native';
export const MyContext = React.createContext();
export default class App extends Component {
state = { value: 12};
render() {
return (
<MyContext.Provider value={this.state}>
<View
style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}>
<Text>Hello There </Text>
<MyContext.Consumer>
{({ value }) => <Text>{value}</Text>}
</MyContext.Consumer>
</View>
</MyContext.Provider>
);
}
}
Kindly check context example. hope it helps
Please check the working example here https://snack.expo.dev/#gaurav1995/excited-donut
import React,{useContext,useState,createContext} from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
const BasicContext = createContext({})
const BasicComp = () => {
const dummyText = useContext(BasicContext);
return(
<View style={styles.container} >
<Text>{dummyText?.hey}</Text>
</View>
)
}
export default function App() {
const [reach,setReach] = useState({ hey:"whatsup devs! loving context"})
return (
<BasicContext.Provider value={reach} >
<BasicComp />
</BasicContext.Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

Unable to navigate using reusable card components in React Native

I have this HomeScreen file, in it I have added Card component(Dashboard & Highlights), I have Customized the Card Components with the TitleCard to reuse the styling,
In each card there is "View All" Button to navigate to its individual Screens,
When I don't use the Cards and put the entire code in home screen and Click on the View All Button on home screen then it navigates to that page, but when I use the Cards and use its props to navigate to the link provided as forwardLink props then
I get this error
"ReferenceError: Can't find variable: navigation"
Also when I add this.props.navigation.navigate('{props.forwardLink}') in TitleCard
I get this error message:
TypeError: undefined is not an object (evaluating '_this.props.navigation')
Here are the codes for each file
TitleCards
import React from 'react';
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
const TitleCards = props => {
return (<View style={styles.textTitlesContainer}>
<Text style={styles.textTitle}>{props.leftTitle}</Text>
<TouchableOpacity
onPress={() => navigation.navigate('{props.forwardLink}')}>
<Text style={[styles.textTitle, {color: '#F483A7'}]}>
{props.rightTitle}
</Text>
</TouchableOpacity>
</View>)
};
const styles = StyleSheet.create({
textTitlesContainer: {
flex: 1,
width: '100%',
flexDirection: 'row',
justifyContent: 'space-between',
padding: 5,
},
textTitle: {
fontSize: 20,
fontWeight: '800',
color: '#fff',
},
});
export default TitleCards;
HomeScreen
import React, {Component} from 'react';
import {
SafeAreaView,
ScrollView,
StyleSheet,
} from 'react-native';
import {CustomHeader} from '../index';
import Colors from '../constants/Colors';
import DashboardCard from './DashboardCard';
import HighlightCard from './HighlightCard';
export class HomeScreen extends Component {
render() {
return (
<SafeAreaView style={{flex: 0, backgroundColor: Colors.primary}}>
<CustomHeader
title="Home"
isHome={true}
navigation={this.props.navigation}
/>
<ScrollView style={styles.container}>
<DashboardCard />
<HighlightCard />
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
height:900, backgroundColor: Colors.mainBackground,
paddingTop:6,
},
});
export default HomeScreen;
HighlightCard
import React, {Component} from 'react';
import {Text, View} from 'react-native';
import {CustomHeader} from '../../index';
const HighlightCard = (prop) => {
return (
<Card>
<TitleCards leftTitle="Highlights" rightTitle="View More" forwardLink="Highlights">
</TitleCards>
<View>
<Text>News Feed</Text>
</View>
</Card>
);
};
export default HighlightCard;
const styles = StyleSheet.create({
textTitle: {
fontSize: 20,
fontWeight: '800',
color: '#fff',
},
});
When I use the HighlightCard codes directly in HomeScreen then it navigates to that page, below is that code which works if I use it directly in Home Screen
*{/* <Text style={styles.textTitle}>Highlights</Text>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Highlights')}>
<Text style={[styles.textTitle, {color: '#F483A7'}]}>View All</Text>
</TouchableOpacity> */}*
I think there is something wrong I am doing is using the props or referencing to the navigation page
I also tried creating a const for navigation
const {navigate} = this.props.navigation
this didn't worked either

How to write Custom flash message in react native

I want to display a custom message after successful record update when boolean value of recordUpdateSuccess become true and after 3seconds it should disappear.
{recordUpdateSuccess ? this.renderRecordUpdatedSucess() : null}
I have function to display message:
renderRecordUpdatedSucess = () => (
<View style={styles.sucessAlert}>
<Text style={styles.sucessAlert}>Record updated successfully.</Text>
</View>
)
I tried to use setTimeout() to display message but not working.
Any idea to acheive this one.
I don't want to use Toast, any third party library for this one.
Custom flash message (No external Library)
Working Example: https://snack.expo.io/#msbot01/1dcddc
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
flashMessage: false
}
}
onPress(){
this.setState({
flashMessage: true
},()=>{setTimeout(() => this.closeFlashMessage(), 3000)})
}
closeFlashMessage(){
this.setState({
flashMessage: false
})
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={()=>{this.onPress()}}>
<Text>Click Me</Text>
</TouchableOpacity >
{this.state.flashMessage==true?
<View style={styles.flashMessage}>
<Text style={{color:'white'}}>This is custom Flash message</Text>
</View>
:
null
}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
flashMessage:{
position:'absolute',
backgroundColor:'green',
width:'100%',
justifyContent:'center',
alignItems:'center',
height:40,
top:0
}
});

React Native code explanation

I have a simple app application project that I would appreciate if someone would explain the logic behind the code.
On the click on the button the text that is inside the text input appears on the imageBackground.
FilterView.js:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image,
Button, Platform, TouchableOpacity, TextInput, ImageBackground } from 'react-native';
import { captureRef } from "react-native-view-shot";
import { Input } from 'react-native-elements';
import DynamicText from './DynamicText';
export default class FilterView extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
imageURI: 'https://reactnativecode.com/wp-content/uploads/2018/02/motorcycle.jpg',
}
}
captureScreenFunction = () => {
captureRef({
format: "jpg",
quality: 0.8
})
.then(
uri => this.setState({ imageURI: uri }),
error => console.error("Oops, Something Went Wrong", error)
);
}
onTextReceived = (text) => {
this.setState({text});
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button title="Capture Device Screenshot" onPress={this.captureScreenFunction} />
<ImageBackground source={{uri: this.state.imageURI}} style={{
width: 200,
height: 300,
marginTop: 5,
alignItems: 'center',
justifyContent: 'center'
}}>
<Text style={{color: 'white'}}>{this.state.text}</Text>
</ImageBackground>
<View style={{ flexDirection: 'row', justifyContent: 'space-around' }}>
<View>
<DynamicText onChangeText={this.onTextReceived}/>
</View>
</View>
</View>
);
}
}
DynamicText.js:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, Button, Platform, TouchableOpacity, TextInput, ImageBackground } from 'react-native';
export default class DynamicText extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
mode: 1 // 1 = edit, 2 = view
}
}
onChange = (text) => {
this.setState({text});
this.props.onChangeText(text);
}
render() {
return (
<View ref="dymanicView">
<TextInput
ref="newItemText"
style={{ height: 40 }}
placeholder="Type something..."
onChangeText={(text) => this.onChange(text)}
/>
</View>
)
}
}
DynamicText.defaultProps = {
onChangeText: () => {}
}
I would like to understand about the defaultProps. For instance what does it do and when can I use it. Also please explain step by step the order of defining and transferring data between the components.
First of all, stackoverflow is not a platform for this type of question. You have to understand first by yourself and then still you have any doubt then put it with code. Anyways I'll explain how it will call when you run your project.
step-1:
first of all FilterView.js is loaded then load everything which you wrote in import tag and in render function.
step-2
then this.state is mutable. This means that state can be updated in the future while props can't. we can initialize state in the constructor, and then call setState when we want to change it.
step-3
then render method call which display what you want/write.
step-4
then captureScreenFunction is a function which you have to call onPress event of Button and onTextReceived is also a function which is call on onTextChange method.
function can bind in different ways but here captureScreenFunction is bind like this captureScreenFunction = () => {} or you can bind like this this.captureScreenFunction = this.captureScreenFunction.bind(this);
step-4
DynamicText.js file get data using this.props which is write in this file. In this file onChange = (text) => {} which calls onChangeText() function which is wrote inside FilterView.js using this.props.
and at last for default.props I'm giving you a link please refer this.
defaultProps in React Native?
Hope it will help you.

React native doesn't display view from other js file

Hello everyone i am new to react native i just stared learning.
i am trying with react native , i have studied about it and now i am trying to learn it , This is my first day in this,
I just created react native project and created one js file and write view in that created js and imported in index.android.jd but it display default view
here is the code
index.android.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import Compo from './homecomponent'
export default class AwesomeProject extends Component {
render() {
return (
<Compo/>
);
}
}
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
and homecomponent is as follow
import {
AppRegistry,
StyleSheet,
Text,
View,
ToolbarAndroid,
TouchableHighlight
} from 'react-native';
export default class homecomponent extends Component
{
render()
{
return(
<view style={styles.container}>
<ToolbarAndroid style={styles.toolbar0}
title="counter demo"/>
<Text>WOWWWW</Text>
<TouchableHighlight
style={ styles.button} >
<Text style={styles.buttontext}>increment</Text>
</TouchableHighlight>
</view>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent:'center',
alignItems: 'center',
},
button:{
backgroundColor:'deepskyblue',
borderwidth:1,
alignItems:'center',
justifyContent:'center',
alignSelf:'stretch',
height:50,
margin:10,
borderRadius:3
},
buttontext:{
fontSize:20,
color:'#FFF'
},
toolbar: {
alignSelf: 'stretch',
height: 50,
backgroundColor: 'silver',
},
text: {
fontSize:20,
},
cancelButton: {
backgroundColor: '#696969',
},
});
Please give me the suggesction why the view is not update in android.I stuck on that problem since morning.
import homecomponent from './HomeCompo'
Do these two following things:
First, in index.android.js file, update your import Compo from './homecomponent' to import homecomponent from './homecomponent'
Second, in the same file, update your return component inside view. Just Add View and inside that rename the component name as homecomponent.