React Native Reusable Card Component won't Visualize as expected - react-native

Hello there I'm new to react native. I'm trying to create reusable component, not only card component, maybe in future will create other reusable components. Below is the code example of reusable card component that I've created:
Card.js
import React from 'react';
import { View, StyleSheet } from 'react-native';
const Card = props => {
return (
<View style={{...styles.card, ...props.style}}>{props.children}</View>);};
const styles = StyleSheet.create({
card: {
shadowColor: 'black',
shadowOffset: { width: 0, height: 2 },
shadowRadius: 6,
shadowOpacity: 0.26,
elevation: 8,
backgroundColor: 'white',
padding: 20,
borderRadius: 10,
}
});
export default Card;
StartGameScreen.js
import React from 'react';
import { View, Text, StyleSheet, TextInput, Button } from 'react-native';
import Card from '../components/Card';
const StartGameScreen = props => {
return (
<View style={styles.screen}>
<Text style={styles.title}>Start a New Game!</Text>
<Card style={styles.inputContainer}>
<Text>Select a Number</Text>
<TextInput />
<View style={styles.buttonContainer}>
<View style={styles.button}><Button title="Reset" onPress={() => {}} /></View>
<View style={styles.button}><Button title="Confirm" onPress={() => {}} /></View>
</View>
</Card>
</View>
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
padding: 10,
alignItems: 'center'
},
title: {
fontSize: 20,
marginVertical: 10
},
inputContainer: {
width: 300,
maxWidth: '80%',
alignItems: 'center'
},
buttonContainer: {
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
paddingHorizontal: 15
},
button: {
width:100
}
});
export default StartGameScreen;
The Result as below:
I'm expecting it to be as below:
Is it possible to use my above code and have the expected result? or is my code wrong and there is better solution??

Your card component is reusable only mistake is the way you are merging the styles. When you merge styles you should not expand it but use an array of styles. Like below.
const Card = props => {
return (<View style={[styles.card, props.style]}>{props.children}</View>);
};
You can check the below snack for full code.
https://snack.expo.io/#guruparan/e368b9

Related

Text strings must be rendered within a <Text> component. When creating a button

I'm new to react native and trying to create a button, here is my StartScreen:
import React from 'react' import Background from '../components/Background' import AppButton from '../components/AppButton'
export default function StartScreen({ navigation }) {
return(
<Background>
<AppButton title="HEEEY!" size="sm" backgroundColor="#007bff" />;
</Background>
) }
Here is my AppButton:
import React from 'react'
import { StyleSheet, TouchableOpacity, Text } from "react-native";
export default function AppButton ({ onPress, title, size, backgroundColor }) {
return (
<TouchableOpacity
onPress={onPress}
style={[
styles.appButtonContainer,
size === "sm" && {
paddingHorizontal: 8,
paddingVertical: 6,
elevation: 6
},
backgroundColor && { backgroundColor }
]}
>
<Text style={[styles.appButtonText, size === "sm" && { fontSize: 14 }]}>
{title}
</Text>
</TouchableOpacity>
)
};
const styles = StyleSheet.create({
screenContainer: {
flex: 1,
justifyContent: "center",
padding: 16
},
appButtonContainer: {
elevation: 8,
backgroundColor: "#009688",
borderRadius: 10,
paddingVertical: 10,
paddingHorizontal: 12
},
appButtonText: {
fontSize: 18,
color: "#fff",
fontWeight: "bold",
alignSelf: "center",
textTransform: "uppercase"
}
});
Here is my Background:
import React from 'react'
import { ImageBackground, StyleSheet, KeyboardAvoidingView } from 'react-native'
import { theme } from '../core/theme'
export default function Background({ children }) {
return (
<ImageBackground style={styles.background}>
<KeyboardAvoidingView style={styles.container} behavior="padding">
{children}
</KeyboardAvoidingView>
</ImageBackground>
)
}
const styles = StyleSheet.create({
background: {
flex: 1,
width: '100%',
backgroundColor: theme.colors.surface,
},
container: {
flex: 1,
padding: 20,
width: '100%',
maxWidth: 340,
alignSelf: 'center',
alignItems: 'center',
justifyContent: 'center',
},
})
When I try to run the application in my Android phone I get the following error:
Error: Text strings must be rendered within a component.
Blockquote
But I cant figure out where this error happens. Can someone spot the mistake?
You have an unnecessary semicolon (;) in your StartScreen JSX, remove it.
export default function StartScreen({ navigation }) {
return(
<Background>
<AppButton title="HEEEY!" size="sm" backgroundColor="#007bff" />
</Background>
); }

Navigating among three screens

I am about to making an app with React Native and I have three screens with deferent styles (themes). I want to navigate among these three screens, So I am passing data from my main screen (App.js) as parent to the other three as child (screen1, screen2, screen3). I used a modal which has three button in it and i want whenever I pressed one of them, the screen change to the pressed one. This is my App.js file
import React, { useState, useEffect } from "react";
import { StyleSheet, View } from "react-native";
import Screen1 from "./screens/CalcScreen";
import Screen2 from "./screens/Screen1";
import Screen3 from "./screens/Screen2";
export default function App() {
const [whiteScreen, setWhiteScreen] = useState(false);
const [darkScreen, setDarkScreen] = useState(false);
const [pinkScreen, setPinkScreen] = useState(false);
const whiteScreenHandler = () => {
setWhiteScreen(true);
setDarkScreen(false);
setPinkScreen(false);
};
const darkScreenHandler = () => {
setDarkScreen(true);
setWhiteScreen(false);
setPinkScreen(false);
};
const pinkScreenHander = () => {
setPinkScreen(true);
setWhiteScreen(false);
setDarkScreen(false);
};
let content = <screen1 setDarkScreen={darkScreenHandler} />;
let content2 = <Screen2 setWhiteScreen={whiteScreenHandler} />;
let content3 = <Screen3 setPinkScreen={pinkScreenHander} />;
if (darkScreen) {
content = content;
} else if (whiteScreen) {
content = content2;
} else if (pinkScreen) {
content = content3;
}
return <View style={styles.container}>{content}</View>;
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#374351",
},
});
And this is one of my screens and my modals in my screens, the other two screens are same in coding but not in styles and I used this modal in each three screens,(does it right to use in three screens?) anyway whenever I'm pressing modal's button to change the screens i got props.screen handler() is not a function. What is wrong in my code?
import React, { useState } from "react";
import {
StyleSheet,
Text,
ScrollView,
View,
TouchableOpacity,
Alert,
Animated,
Modal,
Pressable,
} from "react-native";
const Screen1 = (props) => {
return (
<View style={styles.screen}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<View style={styles.button}></View>
<Text style={styles.modalText}>Themes</Text>
<TouchableOpacity
style={styles.darkTheme}
onPress={() => {
props.setDarkScreen();
}}
>
<Text>Dark</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.whiteTheme}
onPress={() => {
props.setWhiteScreen();
}}
>
<Text>White</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.pinkTheme}
onPress={() => {
props.setPinkScreen();
}}
>
<Text>Pink</Text>
</TouchableOpacity>
<Pressable
style={[styles.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styles.textStyle}>X</Text>
</Pressable>
</View>
</View>
</Modal>
<Pressable
style={[styles.button, styles.buttonOpen]}
onPress={() => setModalVisible(true)}
>
<Text style={styles.openText}>{">"}</Text>
</Pressable>
</View>
)
}
const styles = StyleSheet.create({
screen: {
backgroundColor: "#fafcff",
},
centeredView: {
// flex: 1,
marginStart: 15,
justifyContent: "center",
alignItems: "center",
// marginTop: 70,
},
modalView: {
marginTop: 200,
backgroundColor: "rgba(255,255,255,0.5)",
borderRadius: 20,
padding: 20,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.5,
shadowRadius: 4,
elevation: 5,
},
button: {
borderRadius: 15,
padding: 10,
elevation: 2,
justifyContent: "center",
alignItems: "center",
marginTop: 20,
},
buttonOpen: {
backgroundColor: "rgba(1,143,132,0.6)",
position: "absolute",
marginTop: 45,
marginStart: -25,
elevation: 2,
height: 70,
width: 40,
},
buttonClose: {
backgroundColor: "rgba(1,1,1,1)",
height: 40,
width: 40,
borderRadius: 50,
// padding: 10,
elevation: 2,
justifyContent: "center",
alignItems: "center",
marginTop: 20,
},
textStyle: {
color: "white",
// fontWeight: "bold",
textAlign: "center",
},
modalText: {
marginBottom: 10,
textAlign: "center",
},
openText: {
fontSize: 25,
fontWeight: "bold",
color: "white",
textAlign: "right",
},
});
export default Screen1;
You can easily doing that by using "React Native Navigation". Here is the documentation:
https://reactnavigation.org/docs/getting-started. I also recommend you that you might want to create your screens into different files to make your code cleaner.

Why is my style not applied to my child component?

Good evening,
I have been trying to create custom card Component in react native that i can use everywhere i need it.
I apply a part of the style inside the component itself, and for the width, layout etc, where i need it. Then i am trying to use the spread operator to "merge" all the properties in the style of the child component. I saw it in a video tutorial, but it's not working for me, and i don't see what is wrong in my code :
import React from 'react';
import { View, Text, StyleSheet, TextInput, Button } from 'react-native';
import Card from '../components/Card';
import Color from '../constants/colors'
import Input from '../components/Input'
const StartGameScreen = props => {
return (
<View style={styles.screen}>
<Text style={styles.title}>Start a New Game!</Text>
<Card style={styles.inputContainer}>
<Text>Select a Number</Text>
<Input />
<View style={styles.buttonContainer}>
<Button title="Reset" color={Color.accent} onPress={() => {}} />
<Button title="Confirm" color={Color.primary} onPress={() => {}} />
</View>
</Card>
</View>
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
padding: 10,
alignItems: 'center'
},
title: {
fontSize: 20,
marginVertical: 10
},
inputContainer: {
width: 300,
maxWidth: '80%',
alignItems: 'center',
},
buttonContainer: {
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
paddingHorizontal: 15
},
input: {
width: 50
}
});
export default StartGameScreen;
And the child component :
import React from 'react';
import { View, StyleSheet } from 'react-native';
const Card = props => {
return (
<View style={{ ...styles.card, ...props.style }}> {props.children}</View>
);
};
const styles = StyleSheet.create({
card: {
shadowColor: 'black',
shadowOffset: { width: 0, height: 2 },
shadowRadius: 6,
shadowOpacity: 0.26,
elevation: 8,
backgroundColor: 'white',
padding: 20,
borderRadius: 10
}
});
export default Card;
Note : I tried with input and card, it's working for none of them.
Is that something that we were able to do but we can't anymore ?
Thank you
Have a nice weekend
Try this:
const Card = props => {
return (
<View style={[styles.card, props.style ]}> {props.children}</View>
);
};

How to create a complex view and card in react native

I want to create a custom card in react native and it gets me confused as to use the views.
I have tried to make a card following the tutorial but I am not getting anywhere since its very confusing.The image below is what I'm trying to achieve.
This is what I have
trying to make the card
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Platform } from "react-native";
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.squareShapeView}/>
<View style={{flex:0.7}}>
<Text>Test1</Text>
<Text>Test1</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
marginTop:50,
justifyContent: 'center',
alignItems:'center',
flexDirection:'row',
borderWidth:0.3,
marginLeft:30,
marginRight:30
},
squareShapeView: {
//To make Square Shape
width:20,
height:70,
backgroundColor: '#14ff5f',
alignSelf:'flex-start'
},
});
This is what I expect to get
this is what I expect
I hope this might help you
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { MaterialIcons } from '#expo/vector-icons';
import { Constants } from 'expo';
// You can import from local files
import AssetExample from './components/AssetExample';
const Card = ({ title, desc }) => (
<View style={styles.cardContainer}>
<View style={styles.cardContent}>
<View style={{ flexDirection: 'column' }}>
<Text>{title}</Text>
<Text>{desc}</Text>
</View>
<MaterialIcons name="navigate-next" size={40} color="red" />
</View>
</View>
)
export default class App extends React.Component {
constructor(props) {
super(props);
this.cards = [
{
title: 'Top up',
desc: 'Top up any number'
},
{
title: 'Top up history',
desc: 'View all of the top up you have made'
}
]
}
renderCards = () => {
return this.cards.map(card => (
<Card
title={card.title}
desc={card.desc}
/>
))
}
render() {
return (
<View style={styles.container}>
{this.renderCards()}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 25,
},
cardContainer: {
paddingTop: 30,
paddingBottom: 30,
shadowColor: 'rgba(0, 0, 0, 0.5)',
shadowOffset: { x: 0, y: 10 },
shadowOpacity: 1,
borderLeftColor: 'blue',
borderLeftWidth: 10,
alignSelf: 'stretch',
backgroundColor: 'white',
marginTop: 20,
},
cardContent: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginLeft: 20,
}
});
https://snack.expo.io/#xavier96/aGVscC

Progress Dialog in ReactNative

I'm pretty new to ReactNative world. Im struggling to find an api or a library that shows the Progress Dialog as below in React Native. I believe ActivityIndicator can be used, but it does not show as overlay. Can anyone help me how can I show as an overlay using styles or if there is good library to make this.
Thanks
Here is the code to Open Prgressbar:
import React from 'react';
import { Modal, View, Text, ActivityIndicator, Button } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { isProgress: false }
}
openProgressbar = () => {
this.setState({ isProgress: true })
}
render() {
return (
this.state.isProgress ?
<CustomProgressBar />
:
<View style={{ flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' }}>
<Button title="Please click here to Open ProgressBar" onPress={this.openProgressbar} />
</View>
);
}
}
const CustomProgressBar = ({ visible }) => (
<Modal onRequestClose={() => null} visible={visible}>
<View style={{ flex: 1, backgroundColor: '#dcdcdc', alignItems: 'center', justifyContent: 'center' }}>
<View style={{ borderRadius: 10, backgroundColor: 'white', padding: 25 }}>
<Text style={{ fontSize: 20, fontWeight: '200' }}>Loading</Text>
<ActivityIndicator size="large" />
</View>
</View>
</Modal>
);
Expo url for live demo
https://snack.expo.io/#jitendra.mca13/progress-bar-demo
I would approach this by using the React Native Modal component with two Views.
This solution is a React solution and not native, so you will need to style your Modal accordingly for each platform.
import React from 'react';
import {
Modal,
View,
StyleSheet,
Text,
ActivityIndicator
} from 'react-native';
const ProgressDialog = ({ visible }) => (
<Modal
visible={visible}
>
<View style={styles.container}>
<View style={styles.content}>
<Text style={styles.title}>Please Wait</Text>
<View style={styles.loading}>
<View style={styles.loader}>
<ActivityIndicator size="large" />
</View>
<View style={styles.loadingContent}>
<Text>Loading</Text>
</View>
</View>
</View>
</View>
</Modal>
);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, .5)',
alignItems: 'center',
justifyContent: 'center',
},
content: {
padding: 35,
backgroundColor: 'white'
},
title: {
fontSize: 18,
fontWeight: 'bold',
},
loading: {
flexDirection: 'row',
alignItems: 'center',
},
loader: {
flex: 1,
},
loadingContent: {
flex: 3,
fontSize: 16,
paddingHorizontal: 10,
}
})
export default ProgressDialog;
Here's a demo on Expo, of course you will probably want to tweak the CSS.
Android & iOS solution
Create a directory called ProgressDialog
Create index.ios.js and index.android.js
Paste the above code into both index.ios.js and index.android.js
Make CSS changes for iOS
You can use the below npm package which is a very easy and attractive loader with many options.
https://github.com/maxs15/react-native-spinkit
import React from 'react';
import { StyleSheet, View } from "react-native";
import Spinner from "react-native-spinkit";
export default LoadingCmpBig = props => {
return (
<View style={styles.container}>
<StatusBar barStyle="default" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
//backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}
});
You can use this component and use it where you want to show the Progress. You just have to maintain the state for visible the loading or not in your render function of the component.