react native asyncstorage how to save and add object - reactjs

I found this piece of code in one of the tutorials, as I understand it, when entering text inside the input, the text is saved in asyncstorage, but how to make that when the button is pressed, an object is formed and added to the state like this {id: 1, name: 'Alex'} how can I reolize it?
import React, { Component } from 'react'
import { StatusBar } from 'react-native'
import { AsyncStorage, Text, View, TextInput, StyleSheet } from 'react-native'
class AsyncStorageExample extends Component {
state = {
'name': ''
}
componentDidMount = () => AsyncStorage.getItem('name').then((value) => this.setState({ 'name': value }))
setName = (value) => {
AsyncStorage.setItem('name', value);
this.setState({ 'name': value });
}
render() {
return (
<View style = {styles.container}>
<TextInput style = {styles.textInput} autoCapitalize = 'none'
onChangeText = {this.setName}/>
<Text>
{this.state.name}
</Text>
</View>
)
}
}
export default AsyncStorageExample
const styles = StyleSheet.create ({
container: {
flex: 1,
alignItems: 'center',
marginTop: 50
},
textInput: {
margin: 5,
height: 100,
borderWidth: 1,
backgroundColor: '#7685ed'
}
})

You can check following code it will help to solve your problem.
import React, { Component } from "react";
import { StatusBar } from "react-native";
import {
AsyncStorage,
TouchableOpacity,
Text,
View,
TextInput,
StyleSheet,
} from "react-native";
class AsyncStorageExample extends Component {
state = {
name: "",
savedData: "",
};
componentDidMount = () =>
AsyncStorage.getItem("name").then((value) =>
this.setState({ savedData: value })
);
setData = (value) => {
AsyncStorage.setItem("name", JSON.stringify([{ id: 1, name: value }]));
};
getData = (value) => {
AsyncStorage.getItem("name").then((value) =>
this.setState({ savedData: value })
);
};
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.textInput}
autoCapitalize="none"
value={this.state.value}
onChangeText={(value) => {
this.setData(value);
}}
/>
<Text>{this.state.savedData}</Text>
<TouchableOpacity
activeOpacity={0.5}
onPress={() => {
this.setData(this.state.name);
}}
>
<View style={styles.saveButton}>
<Text style={styles.textStyle}>{"Save Data"}</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
activeOpacity={0.5}
onPress={() => {
this.getData(this.state.name);
}}
>
<View style={styles.saveButton}>
<Text style={styles.textStyle}>{"Get Data"}</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
export default AsyncStorageExample;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
marginTop: 50,
},
textStyle: {
color: "white",
textAlign: "center",
},
saveButton: {
width: 100,
height: 40,
marginBottom:10,
marginTop:15,
borderRadius: 8,
borderColor: "white",
justifyContent: "center",
borderWidth: 1,
color: "white",
backgroundColor: "#7685ed",
},
textInput: {
width: "80%",
height: 100,
borderRadius: 5,
borderWidth: 1,
backgroundColor: "#7685ed",
},
});

Related

React Native Error: Element type is invalid (Formik)

I have a problem with Login Screen I am using Formik to use custom TextInputs but I am getting this error: (Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.)
This is my LoginScreen.js
import React, {useState} from 'react';
import { Alert,
Image,
KeyboardAvoidingView,
ScrollView,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native';
import AppText from '../../components/AppText';
import AppButton from '../../components/AppButton';
import colors from '../../configs/colors';
import AppInput from '../../components/AppInput';
import {Formik} from 'formik';
import * as Yup from 'yup';
import http from '../../services/http';
import storage from '../../services/storage';
import {setUser} from '../../store/reducers/auth';
import {CommonActions} from '#react-navigation/native';
import {useDispatch} from 'react-redux';
import ProgressDialog from 'react-native-progress-dialog';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
const LoginScreen = ({navigation}) => {
const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const loginUser = async values => {
try {
setLoading(true);
values['role'] = 2;
values['device_token'] ='XYZ';
const res = await http.post({
url: '/user/login',
body: values,
});
console.log('Res => ', res.data);
if (res.data.records.isVerified === 1) {
dispatch(setUser(res.data));
http.setUserTokenAndId(
res.data.records.accessToken,
res.data.records.id,
);
await storage.store('USER', res.data);
navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [{name: 'Home'}],
}),
);
} else {
Alert.alert('Error', res.data.message, [
{
text: 'Resend Email',
onPress: () => {
resendEmail(res.data.records.accessToken);
},
style: 'destructive',
},
{
text: 'Cancel',
onPress: () => {},
style: 'cancel',
},
]);
}
} catch (err) {
console.log('Err => ', err);
} finally {
setLoading(false);
}
};
const resendEmail = async token => {
try {
setLoading(true);
const res = await http.post({
url: '/email/verification-notification',
body: {},
headers: {Authorization: 'Bearer ' + token},
});
Alert.alert('Success', res.data.message);
} catch (err) {
console.log('Err', err);
} finally {
setLoading(false);
}
};
return (
<View style={styles.container}>
<View style={styles.cardContainer}>
<View style={styles.card}>
<View>
<KeyboardAwareScrollView style={{height: '100%'}}>
<>
<Image source={require('../../assets/header.png')} />
<AppText style={styles.headingText}>Sign In To Forsa</AppText>
<AppText style={styles.subHeadingText}>
Welcome Back! sign in to your previous account to continue the
shoping
</AppText>
</>
<View>
<Formik
initialValues={{email: '', password: ''}}
validationSchema={Yup.object({
email: Yup.string().label('Email').required(),
password: Yup.string().label('Password').min(5).required(),
})}
onSubmit={loginUser}>
{({submitForm}) => {
return (
<View>
<Image
style={{
alignItems: 'center',
marginTop: 10,
height: 150,
width: '100%',
}}
resizeMode="contain"
source={require('../../assets/loginicon.png')}
/>
<View style={{marginHorizontal: 20}}>
<AppInput
label=""
placeholder="Email*"
keyboardType="email-address"
name="email"
iconName="email"
autoComplete={true}
inputStyle={styles.input}
inputWrapperStyle={styles.inputWrapper}
/>
<AppInput
label=""
placeholder="Password*"
name="password"
secureTextEntry={true}
iconName="lock"
inputWrapperStyle={styles.inputWrapper}
inputStyle={styles.input}
/>
</View>
<AppButton
containerStyle={styles.loginBtn}
onPress={submitForm}
title={'Login'}></AppButton>
<View
style={{
justifyContent: 'space-between',
flexDirection: 'row',
marginTop: 10,
}}>
<View />
<AppText
style={{
color: colors.TAB_BAR_GREY,
fontSize: 13,
marginRight: 25,
}}
onPress={() =>
navigation.navigate('forgotPassword')
}>
Forgot Password?
</AppText>
</View>
<View
style={{
justifyContent: 'center',
flexDirection: 'row',
marginTop: 10,
}}>
<AppText>Don't have any account yet?</AppText>
<TouchableOpacity
onPress={() =>
navigation.navigate('CreateAccount')
}>
<AppText
style={{
marginLeft: 10,
color: colors.PRIMARY_GREEN,
}}>
Sign Up
</AppText>
</TouchableOpacity>
</View>
</View>
);
}}
</Formik>
</View>
</KeyboardAwareScrollView>
</View>
{loading && (
<ProgressDialog
loaderColor={colors.PRIMARY_GREEN}
visible={loading}
labelStyle={{marginTop: 10}}
/>
)}
</View>
</View>
</View>
);
};
export default LoginScreen;
const styles = StyleSheet.create({
headingText: {
fontSize: 30,
position: 'absolute',
marginTop: 80,
marginLeft: 20,
color: colors.WHITE,
fontWeight: '600',
},
subHeadingText: {
fontSize: 18,
position: 'absolute',
marginTop: 120,
marginLeft: 20,
color: colors.WHITE,
fontWeight: '400',
},
loginBtn: {
marginTop: 20,
borderRadius: 50,
marginHorizontal: 20,
},
input: {
paddingLeft: 10,
},
inputWrapper: {
borderWidth: 0.5,
borderRadius: 50,
},
label: {
color: colors.PRIMARY_GREEN,
},
loading: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center',
// backgroundColor: "rgba(66,66,66,0.47)",
},
btnText: {
color: colors.WHITE,
fontSize: 16,
},
});
This is my AppInput.js (Which is custom TextInput):
import React from 'react';
import {View, TextInput, StyleSheet, Platform} from 'react-native';
import AppText from './AppText';
import {useFormikContext} from 'formik';
import colors from '../configs/colors';
import {MaterialCommunityIcons} from 'react-native-vector-
icons/MaterialCommunityIcons';
export default props => {
const {
name,
label,
labelStyle,
inputWrapperStyle,
inputWrapperErrorStyle,
inputStyle,
errorStyle,
containerStyle,
iconName,
value,
multiline = false,
editable = true,
} = props;
const {values, errors, touched, setFieldValue} = useFormikContext();
let wrapperErrorStyle = error
? {
borderWidth: 1,
borderColor: colors.ERROR_TEXT,
...inputWrapperErrorStyle,
}
: {
// borderWidth: 1,
// borderColor: props.value ? colors.LIGHT_GREY : colors.LIGHT_GREY,
...inputWrapperErrorStyle,
};
const error = touched[name] && errors[name];
let iconColor = props.value ? colors.PRIMARY_GREEN : colors.TAB_BAR_GREY;
if (error) iconColor = colors.errorText;
return (
<View style={[styles.containerStyle, containerStyle]}>
<AppText style={[styles.label, labelStyle]}>{label}</AppText>
<View style={[styles.inputWrapper, inputWrapperStyle, wrapperErrorStyle]}>
{iconName && (
<MaterialCommunityIcons
name={iconName}
size={25}
style={styles.iconStyles}
color={iconColor}
/>
)}
<TextInput
{...props}
value={value}
editable={editable}
onChangeText={txt => {
setFieldValue(name, txt);
}}
multiline={multiline}
placeholderTextColor={colors.TAB_BAR_GREY}
style={[styles.input, inputStyle]}
/>
</View>
{error ? (
<AppText style={[styles.error, errorStyle]}>{error}</AppText>
) : null}
</View>
);
};
const styles = StyleSheet.create({
containerStyle: {
marginTop: Platform.OS === 'ios' ? 5 : 0,
marginBottom: 0,
},
label: {
fontSize: 15,
},
inputWrapper: {
flexDirection: 'row',
borderWidth: 0,
},
iconStyles: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 7,
marginLeft: 18,
},
input: {
flex: 1,
minHeight: 40,
maxHeight: 150,
fontSize: 16,
color: colors.BLACK,
},
error: {
color: colors.ERROR_TEXT,
marginTop: 3,
fontSize: 16,
},
});
I am searching from 3-4 hours but couldn't find any solution to this, I am kinda new to react native. Any help will be appreciated. Thank you.

Fetching data from URL works in ReactJS but does not work in Native

Fetching data from URL by search it, it works in React and not working in React Native how to solve the problem?
import React, { Component } from 'react'
import { SafeAreaView, StyleSheet, StatusBar, ScrollView, View, Text, TextInput, Button } from 'react-native';
import axios from 'axios';
export default class Main extends Component {
constructor(props){
super(props)
this.state={
ifscCode:"",
detail:{}
}
}
ifscSearch = () => {
const that = this;
axios.get('https://ifsc.razorpay.com/${this.state.ifscCode}')
.then(function (response) {
if (response.status == 200){
that.setState({detail:response.data})
console.log(data);
}
})
.catch(function (error) {
console.log(error);
})
}
ifscCodeChange = (Value) => {
this.setState({ifscCode:Value})
}
render() {
return (
<>
<StatusBar barStyle="light-content" />
<SafeAreaView>
<ScrollView>
<View style={styles.maincnt}>
<View style={styles.inpcnt}>
<NewIfsc ifscCodeChange={this.ifscCodeChange} />
</View>
<View style={styles.btncnt}>
<Button title='Search' style={styles.btn} onClick={this.ifscSearch} />
</View>
<View style={styles.listcnt}>
<Text>BANK: {this.state.detail.BANK}</Text>
<Text>{this.state.detail.BRANCH}</Text>
<Text>{this.state.detail.STATE}</Text>
<Text>{this.state.detail.CONTACT}</Text>
<Text>{this.state.detail.ADDRESS}</Text>
<Text>{this.state.detail.BANKCODE}</Text>
<Text>{this.state.detail.DISTRICT}</Text>
<Text>{this.state.detail.STATE}</Text>
<Text>{this.state.detail.IFSC}</Text>
</View>
</View>
</ScrollView>
</SafeAreaView>
</>
)
}
}
class NewIfsc extends Component {
render() {
return (
<View style={styles.inpcnt}>
<TextInput style={styles.txtinp} maxLength={11} placeholder='ifsc code search' onChange={(e)=>this.props.ifscCodeChange(e.target.Value)} />
</View>
)
}
}
const styles = StyleSheet.create({
maincnt:{
flex:1,
margin: 10,
backgroundColor: 'white'
},
inpcnt:{
marginTop: 20,
},
btncnt:{
marginTop: 20,
},
listcnt:{
marginTop: 20
},
txtinp:{
width: 350,
height: 50,
borderRadius: 25,
borderWidth: 2,
borderColor: 'indigo',
alignSelf: 'center',
padding: 10
},
btn:{
width: 100,
height: 70,
alignSelf: 'center'
},
listcnt:{
marginTop: 50,
alignContent: 'center',
justifyContent: 'center'
}
});

RN - How to get label from Slider?

I want to get the picker's label chosen by the user and store it in this.state.name, I coded the following but the 'value' is being saved instead. How to get the label?
<Picker
selectedValue={this.state.name}
style={{height: 50, width: 100}}
onValueChange={(label) => this.setState({name: label})}
>
<Picker.Item label="Juan" value="key0" />
<Picker.Item label="Pedro" value="key1" />
<Picker.Item label="David" value="key2" />
</Picker>
Pass items as an array of objects and it can be done easily.
import * as React from 'react';
import { Text, View, StyleSheet, Picker } from 'react-native';
import Constants from 'expo-constants';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
pickerArray: [
{ label: 'Juan', value: 'key0' },
{ label: 'Pedro', value: 'key1' },
{ label: 'David', value: 'key2' },
],
};
}
render() {
return (
<View style={styles.container}>
{this.state.name !== '' && (
<Text style={styles.texto}>
Se ha seleccionado a {this.state.name}
</Text>
)}
<Picker
selectedValue={this.state.value}
style={[styles.picker]}
itemStyle={styles.pickerItem}
onValueChange={person => {
var selectedObj = this.state.pickerArray.find(person1 => {
return person1.value === person;
});
console.log(selectedObj);
if (selectedObj) {
this.setState({ name: selectedObj.label,
value : selectedObj.value
});
}
}}>
{this.state.pickerArray.map(person => {
return <Picker.Item label={person.label} value={person.value} />;
})}
</Picker>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
padding: Constants.statusBarHeight,
backgroundColor: 'white',
},
picker: {
width: 200,
height: 44,
backgroundColor: '#FFF0E0',
borderColor: 'red',
borderBottomWidth: 2,
flex: 90
},
pickerItem: {
height: 44,
color: 'white'
},
texto: {
fontSize: 30,
color: 'red',
}
});

How can i create a table using the react-pdf library for generation pdf report?

As the react-pdf library offering some limited component and no html tag is allowed to render in reactpdfrenderer.So i am in a trouble to make table using this library?
Can any one please help me how can i create a table using this react-pdf library components?
You can use as #David-Kucsai told in comment #david.kucsai/react-pdf-table
or without using
Example
Data
const data = {
id: "5df3180a09ea16dc4b95f910",
items: [
{
sr: 1,
desc: "desc1",
xyz: 5,
},
{
sr: 2,
desc: "desc2",
xyz: 6,
},
],
};
app.js
import React, { Component, Fragment } from "react";
import { PDFViewer } from "#react-pdf/renderer";
import Table from "./components/reports/Table";
import data from "./data";
class App extends Component {
render() {
return (
<Fragment>
<PDFViewer width="1000" height="600">
<Table data={data} />
</PDFViewer>
</Fragment>
);
}
}
export default App;
Table.js
import React from "react";
import { Page, Document, StyleSheet } from "#react-pdf/renderer";
import ItemsTable from "./ItemsTable";
const styles = StyleSheet.create({
page: {
fontSize: 11,
flexDirection: "column",
},
});
const Table = ({ data }) => (
<Document>
<Page size="A4" style={styles.page}>
// ...
<ItemsTable data={data} />
// ...
</Page>
</Document>
);
export default Table;
ItemsTable.js
import React from "react";
import { View, StyleSheet } from "#react-pdf/renderer";
import TableRow from "./TableRow";
const styles = StyleSheet.create({
tableContainer: {
flexDirection: "row",
flexWrap: "wrap",
},
});
const ItemsTable = ({ data }) => (
<View style={styles.tableContainer}>
{/*<TableHeader />*/}
<TableRow items={data.items} />
{/*<TableFooter items={data.items} />*/}
</View>
);
export default ItemsTable;
TableRow.js
import React, { Fragment } from "react";
import { Text, View, StyleSheet } from "#react-pdf/renderer";
const styles = StyleSheet.create({
row: {
flexDirection: "row",
alignItems: "center",
},
description: {
width: "60%",
},
xyz: {
width: "40%",
},
});
const TableRow = ({ items }) => {
const rows = items.map((item) => (
<View style={styles.row} key={item.sr.toString()}>
<Text style={styles.description}>{item.desc}</Text>
<Text style={styles.xyz}>{item.xyz}</Text>
</View>
));
return <Fragment>{rows}</Fragment>;
};
export default TableRow;
For more information check Generate Dynamic PDF Invoices Using React and React-PDF
Thanks goes to Yash for the detailed answer given. This is what I ended up creating after seeing your example.
The main trick to create a "table" is to use fixed width columns on each row.
Note: Make the parent container width: '100%' (table in this case) if you want to have your rows add up beyond 100% without overflowing/growing the parent. I would still recommend you try to have your total width add to 100% though, but the example below shows otherwise.
import { StyleSheet, Text, View } from '#react-pdf/renderer'
import PropTypes from 'prop-types'
const styles = StyleSheet.create({
table: {
width: '100%',
},
row: {
display: 'flex',
flexDirection: 'row',
borderTop: '1px solid #EEE',
paddingTop: 8,
paddingBottom: 8,
},
header: {
borderTop: 'none',
},
bold: {
fontWeight: 'bold',
},
// So Declarative and unDRY 👌
row1: {
width: '27%',
},
row2: {
width: '15%',
},
row3: {
width: '15%',
},
row4: {
width: '20%',
},
row5: {
width: '27%',
},
})
const ReportTable = ({ data, maximumDays }) => {
return (
<View style={styles.table}>
<View style={[styles.row, styles.bold, styles.header]}>
<Text style={styles.row1}>Name</Text>
<Text style={styles.row2}>Start Date</Text>
<Text style={styles.row3}>End Date</Text>
<Text style={styles.row4}>Days</Text>
<Text style={styles.row5}>Info</Text>
</View>
{data.map((row, i) => (
<View key={i} style={styles.row} wrap={false}>
<Text style={styles.row1}>
<Text style={styles.bold}>{row.lastName}</Text>, {row.firstName}
</Text>
<Text style={styles.row2}>{row.startDate}</Text>
<Text style={styles.row3}>{row.endDate}</Text>
<Text style={styles.row4}>
<Text style={styles.bold}>{row.days}</Text> of{' '}
{maximumDays}
</Text>
<Text style={styles.row5}>{row.info}</Text>
</View>
))}
</View>
)
}
ReportTable.propTypes = {
data: PropTypes.array.isRequired,
maximumDays: PropTypes.number.isRequired,
}
export default ReportTable
simple table answer here:
showcase
Code:
/* eslint-disable react-hooks/exhaustive-deps */
import React, { Fragment, useEffect, useState } from "react";
import { View, StyleSheet, Text } from "#react-pdf/renderer";
export default function Table({ data }) {
const [tableData, setTableData] = useState();
const styles = StyleSheet.create({
rowView: {
display: 'flex', flexDirection: 'row', borderTop: '1px solid #EEE', paddingTop: 8, paddingBottom: 8, textAlign: "center"
}
});
useEffect(() => {
if (data !== undefined) setTableData(data);
}, []);
return (
<>
{tableData &&
(
<Fragment>
<View style={styles.rowView}>
{tableData["column"].map((c) => <Text style={{
width: `${100 / tableData["column"].length}%`
}}>{c}</Text>)}
</View>
{tableData["data"].map((rowData) => <>
<View style={styles.rowView}>
{tableData["column"].map((c) =>
<Text style={{ width: `${100 / tableData["column"].length}%` }}>{rowData[c]}</Text>
)}
</View>
</>)}
</Fragment>
)}
</>
)
}
data format:
{
"column": [
"price",
"email",
"time"
],
"data": [
{
"price": "",
"email": "",
"time": ""
},
{
"price": "",
"email": "",
"time": ""
}
]
}
the table auto-populates based on the number of columns and auto sizes to take full page. just make sure to use column names as data keys
function checkStrEmpty(str) {
return !(str && str.length > 1 && str.split(" ").join("").length > 0);
}
import { Text, View, StyleSheet } from "#react-pdf/renderer";
import React from "react";
function CustomTablePDF(props) {
const { fields = [], data = [] } = props;
let tableCol = {
borderStyle: BORDER_STYLE,
borderColor: BORDER_COLOR,
borderBottomColor: "#000",
borderWidth: 1,
borderLeftWidth: 0,
borderTopWidth: 0
};
return (
<View style={styles.table}>
<View style={[styles.tableRow, styles.headerBg]}>
{fields.map((_item, _idx) => (
<View
key={_idx}
style={[tableCol, { width: _item.width + "%" }]}
>
<Text
style={[
styles.tableCellHeader,
{ textAlign: "center" }
]}
>
{_item.title}
</Text>
</View>
))}
</View>
{data.map(
(item, idx) =>
item && (
<View key={idx} style={styles.tableRow}>
{fields.map((_item, _idx) => {
let val = item[_item.value] || "";
let value_alt =
(_item.value_alt &&
item[_item.value_alt]) ||
"";
if (_item.custom) {
return (
<View
key={_idx}
style={[
tableCol,
{ width: _item.width + "%" }
]}
>
<Text
style={[
styles.tableCell,
item.style ? item.style : {}
]}
>
{_item.component(item)}
</Text>
</View>
);
} else {
return (
<View
style={[
styles.tableCol,
{ width: _item.width + "%" }
]}
>
<Text
style={[
styles.tableCell,
item.style ? item.style : {}
]}
>
{checkStrEmpty(val)
? value_alt
: val || "-"}
</Text>
</View>
);
}
})}
</View>
)
)}
</View>
);
}
const BORDER_COLOR = "#000";
const BORDER_STYLE = "solid";
const styles = StyleSheet.create({
headerBg: {
backgroundColor: "#aaa"
},
table: {
display: "table",
width: "auto",
borderStyle: BORDER_STYLE,
borderColor: BORDER_COLOR,
borderWidth: 1
// borderRightWidth: 0,
// borderBottomWidth: 0,
},
tableRow: {
margin: "auto",
flexDirection: "row"
},
tableCellHeader: {
margin: 2,
fontSize: 13,
fontWeight: "bold"
// fontFamily: "CustomRoboto",
},
tableCell: {
margin: 2,
fontSize: 12
// fontFamily: "CustomRoboto",
},
textCenter: {
textAlign: "center"
}
});
export default CustomTablePDF;
use the component like this
const fields = [
{
title: " Agent Name",
custom: true,
component: (item) => `${item.agent_name}`,
width: "30"
},
{
title: " Policy No",
custom: true,
component: (item) => `${item.policy_no}`,
width: "35"
},
{
title: "Policy Class",
value: 'policy_class',
width: "20"
},
{
title: "Amount",
custom: true,
style: { textAlign: "right" },
className: "text-right",
component: (item) =>`${formatNumber(item.contribution)}`,
width: "15"
}
];
<CustomTablePDF fields={fields} data={details} />

conditionality render headerRight - React Native

I have to render headerRight conditionally in navigation options.
Right now
static navigationOptions = ({ navigation }) => ({
title: i18N.t('atmbranchpickHeader'),
headerRight: (
<TouchableHighlight
underlayColor="#E22F39"
onPress={() => {
navigation.navigate("home");
}}
>
<Image
style={{ marginRight: 20 }}
source={require('../../resources/toolbar/home_white.png')}
/>
</TouchableHighlight>
),
headerTintColor: "white",
headerStyle: {
backgroundColor: "#E22F39"
// top: 30
}
});
My Component
import React, { Component } from "react";
import {
View,
TextInput,
Text,
TouchableOpacity,
TouchableHighlight,
StyleSheet,
AsyncStorage,
BackHandler,
Image,
FlatList,
Dimensions,
TouchableWithoutFeedback
} from "react-native";
import i18n from "../../i18n/i18n.js";
import { colors } from "../../constants/colors.js";
import Storage from "../../utils/AsyncStorage.js";
class AtmBranchTypeSelect extends Component {
// Render callBack
constructor(props) {
super(props);
this.state = {
data: [
],
stBool: false,
}
}
async componentWillMount() {
BackHandler.addEventListener('hardwareBackPress', () => this.props.navigation.goBack());
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', () => this.props.navigation.goBack());
}
static navigationOptions = ({ navigation }) => ({
title: i18n.t('atmbranchpickHeader'),
headerRight: (
<TouchableHighlight onPress={() => {
navigation.navigate('home');
}}>
<Image style={{ marginRight: 20 }} source={require('../../resources/toolbar/home_white.png')} />
</TouchableHighlight>),
headerTintColor: 'white',
headerStyle: {
backgroundColor: colors.themeColor,
// top: 30
}
});
_renderList = ({ item }) => {
return (
<TouchableWithoutFeedback onPress={(event) => this._selectedItem(item.key)}>
<View style={styles.listRowContainer}>
<View style={styles.listinside1Container}>
<Image style={styles.listImage} source={item.icon} />
<View style={styles.listContainer} onPress={(event) => this._selectedItem(item.text)} >
<Text style={styles.listHeader} >{item.header}</Text>
<Text style={styles.listValue} >{item.value}</Text>
</View>
</View>
<Image style={styles.listimgArrow} source={require('../../resources/toolbar/chevron_right_grey.png')} />
</View>
</TouchableWithoutFeedback>
);
}
// Render callBack
render() {
return (
<View style={styles.mainWrapper} >
<FlatList data={this.state.data} renderItem={this._renderList} />
</View>
);
}
}
const styles = StyleSheet.create({
mainWrapper: {
flex: 1,
height: Dimensions.get('window').height,
width: Dimensions.get('window').width,
flexDirection: 'column',
justifyContent: 'flex-start'
},
listRowContainer: {
flexDirection: 'row',
marginTop: 10,
height: 80,
backgroundColor: '#FFFFFF',
justifyContent: 'space-between',
borderBottomWidth: 1,
borderColor: 'lightgray'
},
listinside1Container: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center'
},
listContainer: {
alignItems: 'flex-start',
justifyContent: 'center',
flexDirection: 'column',
backgroundColor: '#FFFFFF',
// borderBottomWidth: 1,
// borderColor: 'lightgray'
},
listHeader: {
color: 'black',
fontFamily: 'Roboto-Medium',
marginLeft: 10,
fontSize: 18,
},
listValue: {
fontFamily: 'Roboto-Regular',
marginTop: 4,
color: 'black',
marginLeft: 10,
fontSize: 14,
},
listImage: {
alignSelf: 'center',
height: 25,
width: 25,
margin: 10
},
listimgArrow: {
// flex: 1,
// flexDirection:'row',
alignSelf: 'center',
height: 25,
width: 25,
margin: 10
},
listVal: {
borderWidth: 1,
borderRadius: 10,
color: 'darkgreen',
borderColor: 'white',
backgroundColor: 'white',
fontWeight: 'bold'
},
});
export default AtmBranchTypeSelect;
From the code I have, headerRight will be displayed in all scenarios. consider I have a scenario like based on state value I have to enable/disable headerRight Button .
for example this.state.stBool? headerRight:(.....) : null
I have to render in this way.Please guide me to achieve this.
You could nest the navigation options inside the render and toggle it based on the state value. Haven't tested and not positively on performace. Hope it helps.
import React, { Component } from "react";
import {
View,
TextInput,
Text,
TouchableOpacity,
TouchableHighlight,
StyleSheet,
AsyncStorage,
BackHandler,
Image,
FlatList,
Dimensions,
TouchableWithoutFeedback
} from "react-native";
import i18n from "../../i18n/i18n.js";
import { colors } from "../../constants/colors.js";
import Storage from "../../utils/AsyncStorage.js";
class AtmBranchTypeSelect extends Component {
// Render callBack
constructor(props) {
super(props);
this.state = {
data: [],
stBool: false
};
}
async componentWillMount() {
BackHandler.addEventListener("hardwareBackPress", () =>
this.props.navigation.goBack()
);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", () =>
this.props.navigation.goBack()
);
}
_renderList = ({ item }) => {
return (
<TouchableWithoutFeedback onPress={event => this._selectedItem(item.key)}>
<View style={styles.listRowContainer}>
<View style={styles.listinside1Container}>
<Image style={styles.listImage} source={item.icon} />
<View
style={styles.listContainer}
onPress={event => this._selectedItem(item.text)}
>
<Text style={styles.listHeader}>{item.header}</Text>
<Text style={styles.listValue}>{item.value}</Text>
</View>
</View>
<Image
style={styles.listimgArrow}
source={require("../../resources/toolbar/chevron_right_grey.png")}
/>
</View>
</TouchableWithoutFeedback>
);
};
// Render callBack
render() {
const { stBool } = this.state;
const navigationOptions = ({ navigation }) => ({
title: i18n.t("atmbranchpickHeader"),
headerRight: stBool ? (
<TouchableHighlight
onPress={() => {
navigation.navigate("home");
}}
>
<Image
style={{ marginRight: 20 }}
source={require("../../resources/toolbar/home_white.png")}
/>
</TouchableHighlight>
) : null,
headerTintColor: "white",
headerStyle: {
backgroundColor: colors.themeColor
// top: 30
}
});
return (
<View style={styles.mainWrapper}>
<FlatList data={this.state.data} renderItem={this._renderList} />
</View>
);
}
}

Resources