How to do shared element transitions in React Native Web? - react-native

I'm using react-native-web to develop a web&mobile application. I've reached the point when I'd like to introduce better transitions between the screens, and for that reason I'd like to do shared element transitions like the one below:
Because I started with #react-navigation/stack for my routing, I wanted to use a library that would support the same structure I have. It took me quite some time to get the react-navigation-shared-element library working, but it has finally compiled. Unfortunately, the animations aren't looking like I wanted them to:
As you can see, there is no animation really. It simply switches the page. I've spent weeks on this issue attempting different config, libraries, and generally everything, and I have nearly given up and started looking for web-only libraries to split the code into two different versions.
Therefore, I kindly request assistance to get the code working with one library or, if you think there are better solutions, an alternative selection of web-only and mobile-only libraries which I could use to keep roughly the same codebase (for example by wrapping library components into something I can use in the code).
Here's the code I have for my current animation:
import React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createSharedElementStackNavigator, SharedElement} from 'react-navigation-shared-element';
import {View, TouchableOpacity, Text} from 'react-native';
const Stack = createSharedElementStackNavigator();
function A({navigation}) {
return (
<View>
<TouchableOpacity onPress={() => navigation.navigate('B')}>GO</TouchableOpacity>
<SharedElement id={'shared'}>
<Text style={{position: 'absolute', top: 50, background: 'yellow'}}>Start screen</Text>
</SharedElement>
</View>
);
}
function B({navigation}) {
return (
<View>
<TouchableOpacity onPress={() => navigation.navigate('A')}>GO</TouchableOpacity>
<SharedElement id={'shared'}>
<Text style={{position: 'absolute', top: 100, background: 'yellow'}}>Start screen</Text>
</SharedElement>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name={'A'} component={A} />
<Stack.Screen
name={'B'}
component={B}
sharedElements={(route, otherRoute, showing) => {
return [
{
id: 'shared',
animation: 'move',
},
];
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
Here are the relevant libraries I am using:
"#react-navigation/native": "^6.0.2",
"#react-navigation/stack": "^6.0.7",
"react-native-shared-element": "^0.8.2",
"react-navigation-shared-element": "^3.1.3"
And, finally, here's my webpack config, which I added it only to support the shared elements library, so I have no idea if it's good or not. I'm quite new to React, so I don't know if there are things like loaders or presets required to support the shared elements animations missing.
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const appDirectory = path.resolve(__dirname);
const babelLoaderConfiguration = {
test: /\.js$/,
include: [
path.resolve(appDirectory, 'src'),
],
use: {
loader: 'babel-loader',
options: {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-web'],
},
},
};
const imageLoaderConfiguration = {
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
esModule: false,
},
},
};
module.exports = {
entry: path.resolve(appDirectory, 'src', 'index.js'),
output: {
filename: 'bundle.web.js',
path: path.resolve(appDirectory, 'build'),
},
devtool: 'source-map',
module: {
rules: [babelLoaderConfiguration, imageLoaderConfiguration],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(appDirectory, 'public', 'index.html'),
filename: 'index.html',
}),
new Dotenv({
path: path.resolve(appDirectory, '.env'),
safe: true,
}),
],
resolve: {
alias: {
'react-native$': 'react-native-web',
},
extensions: ['.web.js', '.js'],
},
};

Try to use minus margin with useState in one component :
LIVE example - https://snack.expo.dev/8ZCuner6B
import React, { Component } from 'react';
import { Alert, Button, Text, TouchableOpacity, TextInput, View, StyleSheet } from 'react-native';
const App = () => {
const [animationStyle , setAnimationStyle] = React.useState({
width: 200,
fontFamily: 'Baskerville',
fontSize: 20,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: 'white',
marginTop:30,
marginVertical: 10,
zIndex:2,
})
const frogotPasswordHandler = () => {
let margin = 30;
let step = 3.5
const timerId = setInterval(() =>{
if (margin > -50){
margin = margin - step
updateMarginStyle(margin);
}
if (margin < -50) {
console.log("cleared")
clearInterval(timerId)
}
} , 2);
}
const updateMarginStyle = (num) =>{
setAnimationStyle({
...animationStyle,
marginTop:num,
})
}
return (
<View style={styles.container}>
<Text style={styles.titleText}>Hi, Welcome To</Text>
<Text style={styles.titleText}>Momento</Text>
<View style={styles.textWrapper}>
<TextInput
keyboardType = 'email-address'
onChangeText={(email) => this.setState({ email })}
placeholder='email'
placeholderTextColor = 'white'
style={styles.input}
/>
</View>
<TextInput
onChangeText={(password) => this.setState({ password })}
placeholder={'password'}
secureTextEntry={true}
placeholderTextColor = 'white'
style={animationStyle}
/>
<TouchableOpacity
style={styles.forgotButton}
onPress={frogotPasswordHandler}
>
<Text style={styles.defaultText}>Forgot password</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
>
<Text style={styles.buttonText}> Sign Up / Login </Text>
</TouchableOpacity>
</View>
);
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'salmon',
},
textWrapper:{
backgroundColor:'green',
zIndex:10,
},
titleText:{
fontFamily: 'Baskerville',
fontSize: 50,
alignItems: 'center',
justifyContent: 'center',
},
button: {
alignItems: 'center',
backgroundColor: 'powderblue',
width: 200,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: 'white',
borderRadius: 25,
marginBottom: 10,
},
buttonText:{
fontFamily: 'Baskerville',
fontSize: 20,
alignItems: 'center',
justifyContent: 'center',
},
input: {
width: 200,
fontFamily: 'Baskerville',
fontSize: 20,
height: 44,
padding: 10,
marginTop:20,
borderWidth: 1,
borderColor: 'white',
marginVertical: 10,
},
defaultText:{
},
forgotButton:{
backgroundColor:'gray',
marginBottom:20,
marginTop:10,
}
});

Related

Too Many renders. React Limits the number of renders to prevent infinite loop

am getting an error while running my react native app in expo , my error is Too many renders react limits the number of renders to prevent infinite loop, don't know where am wrong , please try to fix my error. if you have any question please free feel to ask ant time.
Home.js
This is the home.js file where in wrote my all code including css.
import React, { useEffect, useState } from 'react'
import { Text, View, FlatList, StyleSheet, ScrollView, Image } from 'react-native';
import { Avatar } from 'react-native-elements';
import { Searchbar, shadow, Modal, Provider, Portal } from 'react-native-paper';
import { AntDesign } from '#expo/vector-icons';
export default function Home() {
const [searchquery, setSearchquery] = React.useState();
const [visible, setVisible] = React.useState(false);
const showModal = setVisible(true);
const hideModal = setVisible(false);
const containerStyle = { backgroundColor: 'white', padding: 20 };
const [users, setUser] = useState([
{
id: 1,
name: "Ashish Nirvikar"
},
{
id: 2,
name: "Drew Macntyre"
},
{
id: 3,
name: "Jonh Cena"
},
{
id: 4,
name: "Rock Samoa"
},
{
id: 5,
name: "Boby Lashely"
},
])
return (
<View >
<Searchbar
placeholder="Search Contacts"
onChangeText={(query) => setSearchquery(query)}
value={searchquery}
style={{ marginTop: 30, marginHorizontal: 10 }}
/>
<ScrollView>
{
users.map((item, index) => {
return (
<View key={index}>
<Text style={styles.names}>{item.name}</Text>
</View>
)
})
}
</ScrollView>
<Provider>
<Portal>
<Modal visible={visible} onDismiss={hideModal} contentContainerStyle={containerStyle}>
<Text>Example Modal. Click outside this area to dismiss.</Text>
</Modal>
</Portal>
<AntDesign name="plus" size={34} color="black" style={styles.plus} onPress={showModal} />
</Provider>
</View>
);
}
const styles = StyleSheet.create({
customText: {
padding: 10,
marginTop: 20,
textAlign: 'center',
backgroundColor: 'lightgray',
fontWeight: 'bold',
fontSize: 20
},
plus: {
fontSize: 50,
position: 'absolute',
top: 680,
right: 40,
backgroundColor: 'pink',
borderRadius: 15,
borderWidth: 0.5,
padding: 5,
},
names: {
padding: 15,
fontSize: 25,
fontWeight: 'bold',
backgroundColor: 'lightgray',
marginTop: 10,
borderRadius: 20,
color: 'black'
}
});
The showModal and hideModal are functions, define it as a function.
const showModal = () => setVisible(true);
const hideModal = () => setVisible(false);

how to get current flat list item data in reactnative using react-native-swipe-list-view

I'm not getting how to get the current item object of a flat list
I used react-native-swipeout and react-native-swipe-list-view and in both examples I stuck.
And on google I found very big answers. Which are not pointing only the particular issue which confused me a lot.
the below is the deleted function when I used react-native-swipeout plugin
const swipeSettings = {
left: [
{
text: 'Delete',
onPress: () => {
console.log('-----delete-----');
},
type: 'delete',
},
}
All I need is to get the current item object data like below inside onpress() when i tapped the delete button .
{
id: 1,
prodName : "abcdefg",
}
That's all, I came from native script background and in that framework I never faced such issue. Because the documentation was crystal clear. But here In react native everything seems to be complicated for me.
Kindly any one help me.
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={({item, index}) => (
<Swipeout {...swipeSettings}>
<View style={styles.listView}>
<Text style={styles.listViewText}>{item.prodName}</Text>
</View>
</Swipeout>
)}
/>
entire page
import React, {useState} from 'react';
import {View} from 'react-native-animatable';
import {
TextInput,
TouchableOpacity,
FlatList,
} from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/FontAwesome';
import {StyleSheet, Pressable, Text, Button} from 'react-native';
import * as Animatable from 'react-native-animatable';
import Swipeout from 'react-native-swipeout';
import ButtonPressable from '../../components/ButtonPressable';
var sqlite_wrapper = require('./sqliteWrapper');
const DATA = [
{
prodName: 'Added data will look like this',
},
];
const swipeSettings = {
style: {
marginBottom: 10,
},
autoClose: false,
backgroundColor: 'transparent',
close: false,
disabled: false,
onClose: (sectionID, rowId, direction) => {
console.log('---onclose--');
},
onOpen: (sectionID, rowId, direction) => {
console.log('---onopen--');
},
right: [
{
backgroundColor: 'dodgerblue',
color: 'white',
text: 'Edit',
onPress: () => {
console.log('-----edit-----');
},
},
],
left: [
{
backgroundColor: 'red',
color: 'white',
text: 'Delete',
onPress: () => {
console.log('-----delete-----');
sqlite_wrapper.deleteById
},
type: 'delete',
// component : (<ButtonPressable text="delete" />)
},
],
// buttonWidth: 100,
};
const AddProductList = ({route, navigation}) => {
const {navData} = route.params;
const [prodName, setProdName] = useState('');
var [data, setData] = useState(DATA);
return (
<View style={styles.container}>
<Animatable.View
animation="bounceIn"
duration={1000}
style={styles.inputFieldView}>
<TextInput
style={styles.textInput}
onChangeText={(value) => setProdName(value)}
placeholder="Add the Product"
defaultValue={prodName}
/>
<TouchableOpacity
style={styles.addView}
onPress={() => {
sqlite_wrapper
.insert({prodName: prodName}, sqlite_wrapper.collection_product)
.then((result) => {
console.log('---result---');
console.log(result);
if (result.rowsAffected) {
fetchAllData();
}
});
function fetchAllData() {
sqlite_wrapper
.readAll(sqlite_wrapper.collection_product)
.then((resultData) => {
console.log('---resultData---');
console.log(resultData);
setData(resultData);
setProdName('');
});
}
// without sql this is how to update the state having a array
// const updatedArray = [...data];
// updatedArray.push({prodName: prodName});
// setData(updatedArray);
// setProdName('');
}}>
<Icon name="plus" size={16} style={styles.add} color="white" />
</TouchableOpacity>
</Animatable.View>
<Animatable.View
animation="bounceInLeft"
duration={1500}
style={{flex: 1}}>
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={({item, index}) => (
<Swipeout {...swipeSettings}>
<View style={styles.listView}>
<Text style={styles.listViewText}>{item.prodName}</Text>
</View>
</Swipeout>
)}
/>
</Animatable.View>
</View>
);
};
var styles = StyleSheet.create({
container: {
flex: 1,
},
inputFieldView: {
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch',
margin: 10,
},
textInput: {
flex: 1,
backgroundColor: '#b2ebf2',
borderTopLeftRadius: 7,
borderBottomLeftRadius: 7,
fontSize: 16,
},
addView: {
backgroundColor: '#0f4c75',
alignSelf: 'stretch',
alignItems: 'center',
justifyContent: 'center',
borderTopEndRadius: 7,
borderBottomEndRadius: 7,
padding: 9,
},
add: {
padding: 7,
},
listView: {
padding: 20,
backgroundColor: 'green',
margin: 0,
borderRadius: 0,
},
listViewText: {
color: 'white',
},
});
export default AddProductList;
So if I get you right you have one generic swipe setting that you want to adjust to each element in the list.
Try changing the renderItem of the Flatlist like this and let me know how it worked for you:
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={({ item, index }) => {
let right = [...swipeSettings.right]; <---- ADDED
let left = [...swipeSettings.left]; <---- ADDED
right[0].onPress = () => console.log('edit', item.prodName); <---- ADDED
left[0].onPress = () => console.log('delete', item.prodName); <---- ADDED
<Swipeout {...swipeSettings} {...{ right, left}} > <---- CHANGED
<View style={styles.listView}>
<Text style={styles.listViewText}>{item.prodName}</Text>
</View>
</Swipeout>
}}
/>
So what I have done here is sending the generic swipe settings to each instance of Swipeout but changed their "Left" and "Right" in order to overwrite their "onPress" function and adjust it to the rendered item.
I know it is hard to understand it like this and it's probably not the best explanation but I hope it will help you somehow.
EDIT
import React, { useState } from 'react';
import { View } from 'react-native-animatable';
import {
TextInput,
TouchableOpacity,
FlatList,
} from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/FontAwesome';
import { StyleSheet, Pressable, Text, Button } from 'react-native';
import * as Animatable from 'react-native-animatable';
import Swipeout from 'react-native-swipeout';
import ButtonPressable from '../../components/ButtonPressable';
var sqlite_wrapper = require('./sqliteWrapper');
const DATA = [
{
prodName: 'Added data will look like this',
},
];
const AddProductList = ({ route, navigation }) => {
const { navData } = route.params;
const [prodName, setProdName] = useState('');
var [data, setData] = useState(DATA);
const renderItem = ({ item, index }) => {
const swipeSettings = {
style: {
marginBottom: 10,
},
autoClose: false,
backgroundColor: 'transparent',
close: false,
disabled: false,
onClose: (sectionID, rowId, direction) => {
console.log('---onclose--');
},
onOpen: (sectionID, rowId, direction) => {
console.log('---onopen--');
},
right: [
{
backgroundColor: 'dodgerblue',
color: 'white',
text: 'Edit',
onPress: () => console.log('-----edit-----', item.prodName)
},
],
left: [
{
backgroundColor: 'red',
color: 'white',
text: 'Delete',
onPress: () => {
console.log('-----delete-----', item.prodName);
sqlite_wrapper.deleteById
},
type: 'delete',
// component : (<ButtonPressable text="delete" />)
},
],
// buttonWidth: 100,
};
return (
<Swipeout {...swipeSettings}>
<View style={styles.listView}>
<Text style={styles.listViewText}>{item.prodName}</Text>
</View>
</Swipeout>
)
}
return (
<View style={styles.container}>
<Animatable.View
animation="bounceIn"
duration={1000}
style={styles.inputFieldView}>
<TextInput
style={styles.textInput}
onChangeText={(value) => setProdName(value)}
placeholder="Add the Product"
defaultValue={prodName}
/>
<TouchableOpacity
style={styles.addView}
onPress={() => {
sqlite_wrapper
.insert({ prodName: prodName }, sqlite_wrapper.collection_product)
.then((result) => {
console.log('---result---');
console.log(result);
if (result.rowsAffected) {
fetchAllData();
}
});
function fetchAllData() {
sqlite_wrapper
.readAll(sqlite_wrapper.collection_product)
.then((resultData) => {
console.log('---resultData---');
console.log(resultData);
setData(resultData);
setProdName('');
});
}
// without sql this is how to update the state having a array
// const updatedArray = [...data];
// updatedArray.push({prodName: prodName});
// setData(updatedArray);
// setProdName('');
}}>
<Icon name="plus" size={16} style={styles.add} color="white" />
</TouchableOpacity>
</Animatable.View>
<Animatable.View
animation="bounceInLeft"
duration={1500}
style={{ flex: 1 }}>
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={renderItem}
/>
</Animatable.View>
</View>
);
};
var styles = StyleSheet.create({
container: {
flex: 1,
},
inputFieldView: {
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch',
margin: 10,
},
textInput: {
flex: 1,
backgroundColor: '#b2ebf2',
borderTopLeftRadius: 7,
borderBottomLeftRadius: 7,
fontSize: 16,
},
addView: {
backgroundColor: '#0f4c75',
alignSelf: 'stretch',
alignItems: 'center',
justifyContent: 'center',
borderTopEndRadius: 7,
borderBottomEndRadius: 7,
padding: 9,
},
add: {
padding: 7,
},
listView: {
padding: 20,
backgroundColor: 'green',
margin: 0,
borderRadius: 0,
},
listViewText: {
color: 'white',
},
});
export default AddProductList;

Unable to resolve "constants/categories.json" from "screens\GridFilter\GridFilter.js"

I'm new at react-native and trying to build an app. When I try to run my code I'm getting this error................................................................
Failed building JavaScript bundle. Unable to resolve
"constants/categories.json" from "screens\GridFilter\GridFilter.js"
GridFilter.js:
import React from 'react';
import { StyleSheet, Text, View, FlatList, Dimensions, TouchableOpacity } from 'react-native';
import categories from 'constants/categories.json';
import filterIcons from 'components/Icons/filterIcons';
import { isIphoneX } from 'utils';
import fonts from 'theme/fonts';
const formatData = (data, numColumns) => {
const numberOfFullRows = Math.floor(data.length / numColumns);
let numberOfElementsLastRow = data.length - numberOfFullRows * numColumns;
while (numberOfElementsLastRow !== numColumns && numberOfElementsLastRow !== 0) {
data.push({ key: `blank-${numberOfElementsLastRow}`, empty: true });
numberOfElementsLastRow++;
}
return data;
};
const numColumns = 3;
const WIDTH = Dimensions.get('window').width;
function GridFilter({ navigation: { navigate } }) {
const renderItem = ({ item }) => {
if (item.empty === true) {
return <View style={[styles.item, styles.itemInvisible]} />;
}
const Icon = filterIcons[item.icon];
return (
<TouchableOpacity style={styles.item} onPress={() => navigate('SearchTopBarStack')}>
<View style={styles.iconWrapper}>
<Icon width={50} height={50} color="#9f9f9f" />
</View>
<Text style={styles.itemText}>{item.name}</Text>
</TouchableOpacity>
);
};
return (
<View style={styles.container}>
<FlatList
data={formatData(categories, numColumns)}
style={styles.wrapper}
renderItem={renderItem}
numColumns={numColumns}
contentContainerStyle={{ paddingBottom: 150 }}
/>
</View>
);
}
export default GridFilter;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingTop: isIphoneX ? 40 : 20,
},
wrapper: {
flex: 1,
},
iconWrapper: {
margin: 10,
},
item: {
alignItems: 'center',
justifyContent: 'center',
flex: 1,
height: WIDTH / numColumns, // approximate a square
padding: 20,
borderColor: 'gray',
borderWidth: 1,
borderRadius: 5,
backgroundColor: '#f3f3f3',
margin: 5,
},
itemInvisible: {
backgroundColor: 'transparent',
},
itemText: {
color: 'black',
textAlign: 'center',
fontFamily: fonts.REGULAR,
},
});
I tried to delete node modules and rebuild. What should I do?
You should refer to your current directory or file in your import. Try to use './' or '../' when you import path. If you use vscode it will give you auto completions.
"../../" is worked for me.

React native search onChange input text, code structure

I am building a searchBar, whenever I do search I get undefined error because the value doesn't exist in state till I finish the whole value so I know that I will get error yet I am unable to solve it so I am trying to render cards according to the search input I think I did hard code my homeScreen I am not sure if I am doing it even right and here it comes the question to the three if statements inside render that I have is it good practice ? is it professional ? can i do something else which makes code easier to read and shorter ? I was thinking of eliminating the third if but I wasn't able to change state inside the second if so I had to add the toggle search function to let it work any ideas on how to eliminate the third if would be nice ..! thank you in advance guys
homeScreen.js
import axios from 'axios';
import React from 'react';
import {
ActivityIndicator,
ScrollView,
Text,
View,
TouchableOpacity,
TextInput,
} from 'react-native';
import Card from '../Components/Card/card';
export default class HomeScreen extends React.Component {
state = {
shows: [],
isLoading: true,
search: false,
title: '',
};
componentDidMount() {
this.getData();
}
toggleSearch = () => {
console.log('hlelleloe');
this.setState({
search: true,
});
};
getData = () => {
const requestUrls = Array.from({length: 9}).map(
(_, idx) => `http://api.tvmaze.com/shows/${idx + 1}`,
);
const handleResponse = data => {
this.setState({
isLoading: false,
shows: data,
});
};
const handleError = error => {
console.log(error);
this.setState({
isLoading: false,
});
};
Promise.all(requestUrls.map(url => axios.get(url)))
.then(handleResponse)
.catch(handleError);
};
render() {
const {isLoading, shows, search, title} = this.state;
if (isLoading) {
return <ActivityIndicator size="large" color="#0000ff" />;
} else if (!search) {
return (
<View>
<View>
<TouchableOpacity
onPress={this.toggleSearch}
style={{height: 300, width: 300}}>
<Text style={{textAlign: 'center', fontSize: 40}}>
Press to Search
</Text>
</TouchableOpacity>
</View>
<ScrollView style={{backgroundColor: '#E1E8E7'}}>
{shows.length &&
shows.map((show, index) => {
return (
<Card
key={show.data.id}
title={show.data.name}
rating={show.data.rating.average}
source={show.data.image.medium}
genres={show.data.genres}
language={show.data.language}
network={show.data.network}
schedule={show.data.schedule}
summary={show.data.summary}
navigation={this.props.navigation}
/>
);
})}
</ScrollView>
</View>
);
} else if (search) {
console.log(title);
return (
<View>
<TextInput
style={{
height: 100,
width: 100,
borderColor: 'gray',
borderWidth: 1,
}}
onChangeText={searchedTitle => (
<Card title={shows.data.searchedTitle} />
)}
/>
</View>
);
}
}
}
Card.js
import React from 'react';
import {
Image,
View,
Text,
Button,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
import Icon from 'react-native-vector-icons/FontAwesome';
const Card = props => {
return (
<View style={styles.container}>
<Image style={styles.Image} source={{uri: `${props.source}`}} />
<Text style={styles.title}>{props.title}</Text>
<View style={styles.ratingContainer}>
<Text style={styles.rating}>Rating: {props.rating}</Text>
<Icon name="star" size={30} color="grey" />
</View>
<TouchableOpacity
style={styles.button}
onPress={() => {
props.navigation.navigate('Details', {
title: props.title,
rating: props.rating,
source: props.source,
genres: props.genres,
language: props.language,
network: props.network,
schedule: props.schedule,
summary: props.summary,
});
}}>
<Text style={styles.buttonText}>Press for details </Text>
</TouchableOpacity>
</View>
);
};
export default Card;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
},
Image: {
flex: -1,
width: wp('90%'),
height: hp('65%'),
},
title: {
flex: 1,
fontSize: 40,
borderRadius: 10,
color: '#3C948B',
margin: 15,
justifyContent: 'center',
alignItems: 'center',
},
ratingContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'white',
elevation: 6,
justifyContent: 'space-between',
borderWidth: 1,
width: 300,
},
rating: {
fontSize: 25,
paddingLeft: 15,
},
button: {
flex: 1,
color: '#3C948B',
backgroundColor: '#3C948B',
height: hp('7%'),
width: wp('70%'),
margin: 20,
alignItems: 'center',
borderBottomLeftRadius: 10,
borderTopRightRadius: 10,
},
buttonText: {
flex: 1,
fontSize: 25,
},
});
you Need to implement a constructor for your React component.
Typically, in React constructors are only used for two purposes:
Initializing local state by assigning an object to this.state
Binding event handler methods to an instance
Do
state = {
shows: [],
isLoading: true,
search: false,
title: '',
};
replace this with
constructor(props){
super(props);
this.state = {
shows: [],
isLoading: true,
search: false,
title: '',
};
}

How to build a nested navigation In react native

I Have navigation system of createMaterialTopTabNavigator and createDrawerNavigator I try to get a menu bar icon in the top left side of the createMaterialTopTabNavigator but till this moment I can't figure out how to add this element at the particular place , is there any react native property that may correspond to that situation , could you please help
import React, { Component } from "react";
import {.. } from "react-native";
import Icon from 'react-native-vector-icons/MaterialIcons'
import { createSwitchNavigator, createDrawerNavigator ,DrawerItems,createMaterialTopTabNavigator,createStackNavigator} from 'react-navigation'
import screens ...
console.disableYellowBox = true;
const TabBarNavig = createMaterialTopTabNavigator({
Places : {
screen :Players,
navigationOptions: ({ navigation }) => ({
title: 'Placements'
}
)
},
GetPlaces : Teams,
New : Matchs
},
{
tabBarOptions: {
scrollEnabled: true,
labelStyle: {
fontSize: 10,
paddingTop:10
},
tabStyle: {
width: Dimensions.get('window').width / 3,
},
style: {
backgroundColor: '#38A1F3',
height: 80
},
indicatorStyle: {
backgroundColor: '#fff',
},
activeTintColor : 'white',
inactiveTintColor : '#ddd',
showIcon : true,
showLabel: true
}
}
);
const DrawerContent = (props) => (
<ScrollView contentContainerStyle={{flexGrow: 1 }}>
<View
style={{
paddingTop: 35,
paddingBottom : 35,
backgroundColor: '#38A1F3',
alignItems: 'center',
justifyContent: 'center',
color: '#FFF'
}}
>
<Image
source={require('./assets/logo.png')}
style={{width:110,height:110 , marginBottom: 10,borderColor:'#FFF',borderWidth:0}}
/>
</View>
<View style={{ backgroundColor: '#FFF',alignItems: 'flex-start',justifyContent: 'center',marginTop:40,marginLeft:20}}>
<DrawerItems {...props}
getLabel = {(scene) => (
<View style={styles.button}>
<Image source={arry[props.getLabel(scene)]} style={{marginRight:20,width:24,height:24}} />
<Text style={styles.buttonText}>{props.getLabel(scene)}</Text>
</View>
)}
/>
</View>
</ScrollView>
)
const arry = {Home:require('./assets/home.png'),Days:require('./assets/icon.png')};
const AppDrawerNavigator = createDrawerNavigator({
Home: TabBarNavig,
Days: Dating
},
{
contentComponent: DrawerContent,
}
)
const Routes = createSwitchNavigator({
App: AppDrawerNavigator
})
export default Routes;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
buttonText:{
color:'#000',
fontStyle: 'italic',
fontSize: 16,
},
button:{
flexDirection: 'row',
paddingBottom : 20
}
});
As my knowledge, in createBottomTopNavigator according to docs there is no option to add menu left or right docs
you can set left icon through navigationOptions of your component like this
static navigationOptions = ({navigation}) => ({
headerLeft: <Icon name='....' ....../>,
headerRight: <Icon name='....' ....../>
})