React Native code explanation - react-native

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.

Related

Not able to set Initials of <Avatar> based on AsyncStorage value

I am building a React Native IOS App and designing a Header in DrawerNavigator with Avatar and want the Initials inside it based on user logged-in.
Below is the Drawer Header component which is attached to main Navigator.
DrawerHeader.js:
import React, {Component} from 'react';
import { Platform, TouchableOpacity, Image, View, Text, StyleSheet } from 'react-
native';
import AsyncStorage from '#react-native-community/async-storage';
import { Avatar } from 'react-native-elements';
export default class DrawerHeader extends React.Component {
constructor(props) {
super(props);
this.state = {
userName: null
};
this._loadDataFromAsyncStorage();
}
_loadDataFromAsyncStorage = async () => {
const userNameData = await AsyncStorage.getItem('userDatauserid');
const obj = JSON.parse(userNameData);
const userName = obj.name;
alert('_bootstrapAsync in drawerheader'+userName);
this.setState({
userName : userName
})
};
render() {
{!this.state.userName && this._loadDataFromAsyncStorage()}
if (this.state.userName){
return (
<View
style={{
backgroundColor: '#690040',
height: 140,
alignItems: 'center',
justifyContent: 'center',
}}
>
<View style={styles.avatarview}>
<Avatar activeOpacity={0.7} rounded title={this.state.userName} />
</View>
<Text style={styles.userNameView}>{this.state.userName}</Text>
</View>
);
} else {
return (
<View style={{ flexDirection: 'row' }}>
<Text>No User Id</Text>
</View>
)
}
}
}
const styles=StyleSheet.create({
avatarview:{
right:'35%',
top:'10%',
backgroundColor:'blue'
},
userNameView:{
right:'35%',
top:'20%'
}
})
The Alert in the above code is giving correct output as below:
_bootstrapAsync in drawerheader Poornima
, where Poornima is the name of user.Below is the DrawerNAvigator in my app.
I want this to be set in Avatar as P inside the square icon as show in the below picture.
But I am getting the name itself inside the square icon.Can anyone explain how to add state data to the title component of Avatar.Thanks in Advance.
I checked with the code to assign the First character of the userName as below:
title={this.state.userName?.charAt(0)} .But I am getting an error as below:
Because you are passing whole string, it will display whatever you will pass in title props
If you will pass title={'MD'}, it will display MD
If you will pass title={'Michel David'}, it will show whole name
It is mentioned in document itself https://reactnativeelements.com/docs/avatar
In your case if you want first character only, you can write title={this.state.userName?.charAt(0)}
Due to change in requirements,I used email id in the Drawer Nvigator.It is now taking the character at index 0 and displaying the first letter of emailId inside Avatar Icon.Below is the working code:
DrawerHeader.js
import React from 'react';
import { Platform, TouchableOpacity, Image, View, Text, StyleSheet }
from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
import { Avatar } from 'react-native-elements';
export default class DrawerHeader extends React.Component {
constructor(props) {
super(props);
this.state = {
emailId:null
};
this._loadDataFromAsyncStorage();
}
_loadDataFromAsyncStorage = async () => {
const userDatalogin = await AsyncStorage.getItem("userDatalogin");
const obj = JSON.parse(userDatalogin);
console.log(obj);
var emailid = obj.textemailid;
this.setState({
emailId : emailid,
})
};
render() {
{!this.state.emailId && this._loadDataFromAsyncStorage()}
if (this.state.emailId){
return (
<View
style={{
backgroundColor: '#0437F2',
height: 140,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Avatar size='medium'
rounded
backgroundColor='green'
right='35%'
top='10%'
title={this.state.emailId?.charAt(0)} />
</View>
<Text style={styles.userNameView}>{this.state.emailId}</Text>
</View>
);
} else {
return (
<View style={{ flexDirection: 'row' }}>
<Text>No User Id</Text>
</View>
)
}
}
}
const styles=StyleSheet.create({
userNameView:{
right:'15%',
top:'20%'
}
})
I have used emailid instead of username based on change in requirement.Find the below output screen.

How to show loading progress or spinner in the middle of the screen with React Native?

I am developing React Native app.
I was able to solve all problems by myself but this is exception.
I am going to load another screen with bottom tab navigator.
For example, after user login to the app, it should show main home screen which has many pictures and many style sheet effects, icons. Because of that, after login confirm ( I mean after alert of the login confirm), the main home screen appears after a few seconds.
So I want to show some spinner in the login screen while loading main home screen in the background and when it is ready to show, erase spinner and show main home screen.
How can I do this?
My bottom tab navigator was simply created with createBottomTabNavigator() method.
So in your case you can do several things
You can use React Native Activity Indicator -> View
You can use Overlay Library -> react-native-loading-spinner-overlay -> View GitHub
If you like to make loading like facebook / instagram -> then use react-native-easy-content-loader -> View GitHub
Assume that you are using React Native Activity Indicator :
import { ActivityIndicator } from "react-native";
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
};
}
//Get Home Screen Data API Action
componentDidMount() {
this.loadAPI(); // Call home screen get data API function
}
//Login API Function
loadAPI = () => {
this.setState({ isLoading: true }); // Once You Call the API Action loading will be true
fetch(API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json"
}
})
.then(response => response.json())
.then(responseText => {
// You can do anything accroding to your API response
this.setState({ isLoading: false }); // After getting response make loading to false
})
.catch(error => {});
};
render() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
{this.state.isLoading && <ActivityIndicator color={"#fff"} />}
</View>
);
}
}
If you want to hide all the view until loading finish like images, so you can use custom library instead of Activity Indicator.
I have created my custom Loader component. Using this you can display built in ActivityIndicator or your custom gif loader image with overlay.
Loader.js
import React, { Component } from 'react';
import {
StyleSheet,
View,
Modal,
Image,
ActivityIndicator
} from 'react-native';
class Loader extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: this.props.isLoading
}
}
static getDerivedStateFromProps(nextProps) {
return {
isLoading: nextProps.isLoading
};
}
render() {
return (
<Modal
transparent={true}
animationType={'none'}
visible={this.state.isLoading}
style={{ zIndex: 1100 }}
onRequestClose={() => { }}>
<View style={styles.modalBackground}>
<View style={styles.activityIndicatorWrapper}>
<ActivityIndicator animating={this.state.isLoading} color="black" />
{/* If you want to image set source here */}
{/* <Image
source={require('../assets/images/loader.gif')}
style={{ height: 80, width: 80 }}
resizeMode="contain"
resizeMethod="resize"
/> */}
</View>
</View>
</Modal>
)
}
}
const styles = StyleSheet.create({
modalBackground: {
flex: 1,
alignItems: 'center',
flexDirection: 'column',
justifyContent: 'space-around',
backgroundColor: '#rgba(0, 0, 0, 0.5)',
zIndex: 1000
},
activityIndicatorWrapper: {
backgroundColor: '#FFFFFF',
height: 100,
width: 100,
borderRadius: 10,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around'
}
});
export default Loader
Now you can use it when you have to display loading indicator as below :
<Loader isLoading={this.state.isLoading} />
import { ActivityIndicator } from 'react-native';
export default class LoginScreen extends Component {
constructor(props) {
super(props);
this.state = {
spinner : true
}
}
render() {
return (
<View style={{flex : 1, justifyContent: 'center', alignItems: 'center',}}>
{
this.state.spinner &&
<ActivityIndicator color={'#fff'} />
}
</View>
)
}
}
So you can show the SPinner for suppose when you have to load an API or something and when you get the response of api, you can set spinner loading value to false.
For eg :
import {View, ActivityIndicator } from 'react-native';
export default class MainScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
spinner : true
}
}
componentDidMount(){
this.loadApi();
}
loadApi = async() => {
let result = axios.get('url').then((data) =>{
this.setState({spinner:false});
}
).catch((err) => this.setState({spinner:false})
}
render() {
return (
<View style={{flex : 1, justifyContent: 'center', alignItems: 'center',}}>
{
this.state.spinner? <ActivityIndicator color={'#fff'} />:<View><Text>Data loaded</Text></View>
}
</View>
)
}
}
you have to use ActivityIndicator you can have to load this activityindicator before getting data from the server , you have to check below code hope you will understand
import React, {useEffect, useState} from 'react';
import {ActivityIndicator, View, Dimensions} from 'react-native';
import HomeScreen from './Home';
const DataViewer = () => {
const [data, setData] = useState([]);
const {height, width} = Dimensions.get('window');
useEffect(() => {
fetch('http://example.com/movies.json')
.then(response => {
return response.json();
})
.then(myJson => {
setData(myJson);
});
});
return data.length > 0 ? (
<HomeScreen data={data} />
) : (
<View
style={{justifyContent: 'center', alignItems: 'center', height, width}}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
);
};
export default DataViewer;
You can use the Activity indicator as the default loading animation. But you can also use Lottie files to implement custom loading screen animation on your project by installing npm i lottie-react-native or yarn add lottie-react-native

React Native element only visible/usable after pressing a button

New to React Native, having a go at an app idea. Basically I'm just trying to create an TextInput element that appears when I press a Button. Below is my attempt. I'm trying to take advantage of state within my class, but something is off.
Expo is throwing an error of 'null is not an object (evaluating 'this.state.isShowingText')'.
Any ideas?
import React, { Component } from 'react';
import { TextInput, Alert, Button, ScrollView, Text, View, StyleSheet } from 'react-native';
export default class CoolComponent extends Component {
render() {
const nameAdd = () =>{
state = { isShowingText: true };
}
return (
<View style={{ alignItems: 'center', top: 50 }}>
<Title>Some Title</Title>
{this.state.isShowingText ? <TextInput></TextInput> : null}
<ScrollView></ScrollView>
<Button
title="Press me"
onPress={nameAdd}
/>
</View>
);
}
}
The way you handling state is wrong
import React, { Component } from 'react';
import { TextInput, Button, ScrollView, View } from 'react-native';
export default class CoolComponent extends Component {
state = {
isShowingText: false
}
nameAdd = () => {
this.setState({
isShowingText: true
})
}
render() {
return (
<View style={{ alignItems: 'center', top: 50 }}>
{this.state.isShowingText ? <TextInput style={{ width: '50', height: '50', borderWidth: 1 }}></TextInput> : null}
<ScrollView></ScrollView>
<Button
title="Press me"
onPress={this.nameAdd}
/>
</View>
);
}
}
Hope this helps you. Feel free for doubts.

React-Native Constructor

Please help me find what is wrong in the following React-Native code?
It says after constructor (props) should have ';' semicolon. I don't know if I declared it in the right way.
import React from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
export default function App() {
constructor (props){
this.state = {
text: 'HI'
}
}
render () {
return (
<View style={styles.container}>
<TextInput style={styles.input}
placeholder = 'Enter Value...'
placeholderTextColor ='#E74292'
onChangeText = {(text) => {
this.setState({text})
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container:{
flex:1,
backgroundColor:'#F4C724',
},
input :{
marginTop:30,
height:30,
width:30,
borderWidth:2,
padding:10,
borderRadius: 5,
borderColor:'#1287A5'
}
}
);
You should declare the component as class instead of function if you want a constructor:
import React from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
export default class App {
constructor(props) {
this.state = {
text: 'HI'
};
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Enter Value..."
placeholderTextColor="#E74292"
onChangeText={text => {
this.setState({ text });
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F4C724'
},
input: {
marginTop: 30,
height: 30,
width: 30,
borderWidth: 2,
padding: 10,
borderRadius: 5,
borderColor: '#1287A5'
}
});
constructor only works in class based component so switch to class based component rather than . functional whihc is now.
import React from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
export default class App extends React.Component{
constructor(props) {
this.state = {
text: 'HI'
};
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Enter Value..."
placeholderTextColor="#E74292"
onChangeText={text => {
this.setState({ text });
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F4C724'
},
input: {
marginTop: 30,
height: 30,
width: 30,
borderWidth: 2,
padding: 10,
borderRadius: 5,
borderColor: '#1287A5'
}
});
You need to study the difference between functional and class component.
Functional component is just a plain java-script function which also known as stateless component. They do not manage their own state or have access to the lifecycle methods.
for more please follow the link below:
https://medium.com/#Zwenza/functional-vs-class-components-in-react-231e3fbd7108
you can use useState , the dynamic function value loads to the initial variable on load
import React,{ useState } from 'react';
import { View, Text, Button, ImageBackground} from 'react-native';
export default function Home({navigation}){
//function getversion onload
const [initval,setInitval] = useState(()=>{ return '123456'});
return(
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text> {initval} </Text>
</View>
);
}
You cannot have a constructor() in functional components. You should either change function component to class component or go and check out the react doc about React Hooks. You are going to have a better understanding of the differences between react class components and react functional components.

React native snapshot screen

I am building an app for iOS with React native and I would like to know how to take a snapshot of a given screen. I have found this library but I don't know how to use it. Does anyone know how to ?
EDIT:
I used the following code to capture a screen using the library but I get the given error.
try {
captureRef(viewRef, {
format: "jpg",
quality: 0.8
})
.then(
uri => console.log("Image saved to", uri),
error => console.error("Oops, snapshot failed", error)
);
} catch (e) {
console.log(e);
}
The error
ReferenceError: viewRef is not defined
Does anybody know how to fix the error?
Thank you
Sure, but you have to read a little about what a ref is. If you are already using React hooks, check this: https://es.reactjs.org/docs/hooks-reference.html#useref
(if not, just search on how to create a ref in React with createRef)
Basically, a ref is something that will let you identify your component using the same variable even if the component re-renders. So, viewRef in your example should be a reference to a given element. Like:
import React, { useRef } from "react";
function MyComponent() {
const viewRef = useRef();
return <View ref={viewRef}>content</View>
}
So, your draft could be something like:
import React, { useRef } from "react";
import {Button, View, Text} from 'react-native';
import { captureRef } from "react-native-view-shot";
function useCapture() {
const captureViewRef = useRef();
function onCapture() {
captureRef(captureViewRef, {
format: "jpg",
quality: 0.9
}).then(
uri => alert(uri),
error => alert("Oops, snapshot failed", error));
}
return {
captureViewRef,
onCapture
};
}
function MyComponent() {
const { captureViewRef, onCapture } = useCapture();
return (
<>
<View ref={captureViewRef}><Text>content</Text></View>
<Button title="Save" onPress={onCapture} />
</>
);
}
As far as I know, this only generates a temporary file. If you want to see the capture saved into your device, you should use CameraRoll https://facebook.github.io/react-native/docs/cameraroll
I won't cover how to use it here, but it would be something like:
CameraRoll.saveToCameraRoll(uri); // uri being the path that you get from captureRef method
Just notice that your app must ask for proper permission before attempting to save to the device gallery.
hi this can be with the help of react-native-view-shot
this is my parent component
import React, {Component,useRef} from 'react';
import {Platform, StyleSheet, Text, View,Image,Button} from 'react-native';
import { captureRef, captureScreen ,ViewShot} from "react-native-view-shot";
import NewVd from './NewVd';
import Newved from './Newved';
export default class App extends Component {
constructor(){
super();
this.state={
item:null,
captureProcessisReady:false,
myView:false
};
this.func=this.func.bind(this);
}
componentDidMount(){
}
result1=()=>{
console.log("i am here ");
this.setState({captureProcessisReady:true});
}
func = (uri) => {
console.log('ADD item quantity with id: ', uri);
this.setState({item:uri,myView:true});
};
render() {
return (
<View style={styles.container}>
{/* <NewVd
func={this.func}/> */}
<Newved />
<Text>...Something to rasterize...</Text>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Button onPress={()=>this.result1()} title="press Me"/>
<View>
{this.state.captureProcessisReady?( <NewVd func={this.func}/>):null}
</View>
<View>
{this.state.myView?( <Image source={{uri:this.state.item !== null?`${this.state.item}`:'https://picsum.photos/200'}} style={{width:100,height:100}} />):null}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
this is my child component
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import ViewShot from "react-native-view-shot";
class NewVd extends Component {
constructor(props){
super(props);
}
onCapture = uri => {
console.log("do something with ", uri);
this.props.func(uri); //for the parent using callback
}
render() {
return (
<ViewShot onCapture={this.onCapture} captureMode="mount">
<Text>...Something to rasterize...</Text>
</ViewShot>
);
}
}
export default NewVd;