Note: I am a beginner learning React Native. I have two js files (Inputs.js and Styles.js) and I am trying to put them both in a const in my main js file (App.js) but I can only export default one of them. Is there a way I can export both of them or should I rearrange my code in another way?
App.js:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const Home1 = () => {
return (
<Style/>
)
}
const Home2 = () =>{
return (
<Inputs />
)
}
export default Home1; //I am unable to export both Home1 and Home2 here
Style.js:
import React, { Component } from 'react';
import { View, Text, Image, StyleSheet } from 'react-native'
const Style = () => {
return ( <View style = {styles.container}>
<Text style = {styles.text}>
<Text style = {styles.capitalLetter}>
Title Here
</Text>
<Text>
<Text style = {styles.textInput}> {"\n"} {"\n"}{"\n"}Location: </Text>
</Text>
<Text>
<Text style = {styles.textInput}> {"\n"} {"\n"}Time:</Text>
</Text>
<Text>
<Text style = {styles.textInput}> {"\n"} {"\n"}Time: </Text>
</Text>
</Text>
</View>
)
}
export default Style
const styles = StyleSheet.create ({
container: {
//alignItems: 'center',
marginTop: 50,
},
text: {
color: '#41cdf4',
},
capitalLetter: {
color: 'red',
fontSize: 20
},
textInput: {
padding: 22,
//fontWeight: 'bold',
color: 'black'
},
textShadow: {
textShadowColor: 'red',
textShadowOffset: { width: 2, height: 2 },
textShadowRadius : 5
}
})
Inputs.js:
import React, { Component } from 'react'
import { View, Text, TouchableOpacity, TextInput, StyleSheet } from 'react-native'
class Inputs extends Component {
state = {
email: '',
password: ''
}
handleEmail = (text) => {
this.setState({ email: text })
}
handlePassword = (text) => {
this.setState({ password: text })
}
login = (email, pass) => {
alert('email: ' + email + ' password: ' + pass)
}
render(){
return (
<View style = {styles.container}>
<TextInput style = {styles.input}
underlineColorAndroid = "transparent"
placeholder = "Email"
placeholderTextColor = "#9a73ef"
autoCapitalize = "none"
onChangeText = {this.handleEmail}/>
<TextInput style = {styles.input}
underlineColorAndroid = "transparent"
placeholder = "Password"
placeholderTextColor = "#9a73ef"
autoCapitalize = "none"
onChangeText = {this.handlePassword}/>
<TouchableOpacity
style = {styles.submitButton}
onPress = { () => this.login(this.state.email, this.state.password)}>
<Text style = {styles.submitButtonText}>
Submit
</Text>
</TouchableOpacity>
</View>
)
}
}
export default Inputs
const styles = StyleSheet.create({
container: {
paddingTop: 200
},
input: {
margin: 15,
height: 40,
borderColor: '#7a42f4',
borderWidth: 1
},
submitButton: {
backgroundColor: '#7a42f4',
padding: 10,
margin: 15,
height: 40,
},
submitButtonText:{
color: 'white'
}
})
****UPDATED CODE BELOW for the error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.:*****
App.js:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
module.exports = {
Home1() {
return (
<Style/>
);
},
Home2() {
return (
<Inputs/>
);
}
};
Style.js
import React, { Component } from 'react';
import { View, Text, Image, StyleSheet } from 'react-native'
import { Inputs } from "./App.js"
import Home1, {Home2} from './App.js'
const Style = () => {
return ( <View style = {styles.container}>
<Text style = {styles.text}>
<Text style = {styles.capitalLetter}>
Title Here
</Text>
<Text>
<Text style = {styles.textInput}> {"\n"} {"\n"}{"\n"}Your address or location (eg, Nashville, TN): </Text>
</Text>
<Text>
<Text style = {styles.textInput}> {"\n"} {"\n"}Contact 2:</Text>
</Text>
<Text>
<Text style = {styles.textInput}> {"\n"} {"\n"}Contact 3: </Text>
</Text>
</Text>
</View>
)
}
export default Style
const styles = StyleSheet.create ({
container: {
//alignItems: 'center',
marginTop: 50,
},
text: {
color: '#41cdf4',
},
capitalLetter: {
color: 'red',
fontSize: 20
},
textInput: {
padding: 22,
//fontWeight: 'bold',
color: 'black'
},
textShadow: {
textShadowColor: 'red',
textShadowOffset: { width: 2, height: 2 },
textShadowRadius : 5
}
})
Inputs.js
import React, { Component } from 'react'
import { View, Text, TouchableOpacity, TextInput, StyleSheet } from 'react-native'
//import { Style } from "./App.js"
import Home1, {Home2} from './App.js'
class Inputs extends Component {
state = {
email: '',
password: ''
}
handleEmail = (text) => {
this.setState({ Location: text })
}
handlePassword = (text) => {
this.setState({ Time: text })
}
login = (email, time1) => {
alert('Location: ' + email + ' Time: ' + time1)
}
render(){
return (
<View style = {styles.container}>
<TextInput style = {styles.input}
underlineColorAndroid = "transparent"
placeholder = "Location"
placeholderTextColor = "#9a73ef"
autoCapitalize = "none"
onChangeText = {this.handleEmail}/>
<TextInput style = {styles.input}
underlineColorAndroid = "transparent"
placeholder = "Time"
placeholderTextColor = "#9a73ef"
autoCapitalize = "none"
onChangeText = {this.handlePassword}/>
<TouchableOpacity
style = {styles.submitButton}
onPress = { () => this.login(this.state.email, this.state.password)}>
<Text style = {styles.submitButtonText}>
Submit
</Text>
</TouchableOpacity>
</View>
)
}
}
export default Inputs
const styles = StyleSheet.create({
container: {
paddingTop: 200
},
input: {
margin: 15,
height: 40,
borderColor: '#7a42f4',
borderWidth: 1
},
submitButton: {
backgroundColor: '#7a42f4',
padding: 10,
margin: 15,
height: 40,
},
submitButtonText:{
color: 'white'
}
})
You could use module.exports in this case to export an object with two methods. Usage:
export function Home1() {
return (
<Style/>
);
};
export function Home2() {
return (
<Inputs/>
);
};
This is part of your file called App.js, so in order to import it in another file you need to:
import { Home1, Home2 } from "./App.js"
In this case you are using named export. In order to import it properly you explicitly need to use import { Home1, Home2 } with Home1 and Home2 being corresponding names of exported functions.
You can have just one default export and as many exports as you need:
const Home1 = () => {
return <Style/>
}
export const Home2 = () => {
return <Inputs />
}
export default Home1;
And then import it like this:
import Home1, {Home2} from './App'
You can export const, but only one default const.
import React from 'react';
export const myCon1 = (
// your code goes here
);
export const myCon2 = (
// your code goes here
);
in Other side you can import
import { myCon1 , myCon2} from '/path_to_file';
Create a component like the code that is shown below, which works, and shows both the Style.js and the Inputs.js files in the app:
import React, {Component} from 'react';
import { StyleSheet, Text, View, AppRegistry } from 'react-native';
import Style from './Style.js';
import Inputs from './Inputs.js';
export default class App extends Component {
render() {
return (
<View>
<Style/> // here, both the Style and Inputs files can be used
<Inputs/>
</View>
)
}
}
Related
I have this code:
import React, { useState } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
export default function App() {
let str = "Hello ^world text '^Some^' '^Random^' '^Example^' '^Text^' '^Some^' '^more^' '^random^' '^example^' '^text^'!"
let arr = str.split(/\s/g)
let wordBits
const [highlightedWords, setHighlightedWords] = useState(["world", "example", "random"])
function highlighter(word) {
setHighlightedWords((prevState) => {
return(
[word, ...prevState]
)
})
}
return (
<View style={styles.container}>
<Text>
{arr.map((el) => {
wordBits = el.split("^")
token = wordBits[1]
return (
<Text>
{wordBits[0]}
<View style={
highlightedWords.includes(wordBits[1]) ?
styles.highlighted :
styles.regular
}>
<Text onPress={() => {highlighter(wordBits[1])}}>
{wordBits[1]}
</Text>
</View>
{wordBits[2]}{" "}
</Text>
)
})}
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
highlighted: {
backgroundColor: "yellow"
},
regular: {
color: "black"
}
});
I extract the word from surrounding characters and try to pass it in as a function on each component. But instead, it gets set to the final word that got mapped.
Is there a way to pass the words themselves, and not change as the variable changes?
I want to know how I can send a function from my parent component to my child component. Because every time I get the error '"validationFunction" is not a function'. Very need your help. Also I will extend my SigIn component and add there another validation functions, so this is very important to me
SignIn component
import React, { Component } from 'react'
import { View } from 'react-native'
import { MyButton, MyTextInput, Header } from '../uikit'
import { styles } from '../constants/constants'
import { LOG_IN } from '../routes'
import { isEnoughSymbols } from '../validation/isEnoughSymbols'
export class SignIn extends Component {
state = {
symbolsValidation: true
}
isEnoughSymbols = (text) => {
if (text.trim().length < 8)
this.setState({ symbolsValidation: false })
}
render() {
const { mainContainer, buttons } = styles
return (
<View>
<View style={mainContainer}>
<MyTextInput
placeholder={'Email/Login'}
isSecure={false}
errorText={"Incorrect email format!"}
/>
<MyTextInput
placeholder={'Password'}
isSecure={true}
errorText={'Password must contain at least 8 symbols!'}
validationFunction={this.isEnoughSymbols.bind(this)}
/>
<MyTextInput
placeholder={'Confirm password'}
isSecure={true}
errorText={"Passwords don't match"}
/>
<View style={buttons}>
<MyButton
name={'confirm'.toUpperCase()}
onPress={() => this.props.navigation.navigate(LOG_IN)} />
</View>
</View>
</View>
)
}
}
And MyTextInput component
import React, {Component} from 'react'
import { TextInput, View, StyleSheet } from 'react-native'
import { w, width, h } from '../constants/constants'
import { ErrorMessage } from '.'
//import { isEnoughSymbols } from '../validation/isEnoughSymbols'
const MyTextInput = ({ placeholder, isSecure, errorText, validationFunction }) => {
let isValid = true
return (
<View style={styles.container}>
<TextInput
style={styles.text}
placeholder={placeholder}
secureTextEntry={isSecure}
onEndEditing={(e) => validationFunction(e.nativeEvent.text)}
>
</TextInput>
{
isValid ? null : <ErrorMessage
errorText={errorText}
/>
}
</View>
)
}
const styles = StyleSheet.create({
container: {
justifyContent: 'flex-start'
},
text: {
borderBottomWidth: 1,
borderColor: 'black',
fontSize: 30,
width: w - w / 10,
alignSelf: 'center',
textAlign: 'left',
marginTop: 20,
color: 'black'
},
}
)
export { MyTextInput }
The fontSize: 20 and color: 'red' props are displaying instead of the fontSize: 12 and color: 'blue' that is set from the Parent component, but the fontWeight: 'bold' is correctly displayed.
I have a reusable React UI child component that receives some props from its parent like so
import React from "react";
import { Text, StyleSheet } from "react-native";
const BodyText = ( props ) => {
return (
<Text style={styles.bodyText} {...props} >{props.children}</Text>
);
};
const styles = StyleSheet.create({
bodyText: {
fontSize: 20,
color: 'red'
},
});
export default BodyText;
The parent component looks like this
import React from "react";
import { StyleSheet } from "react-native";
import BodyText from './components/UI/BodyText'
const Parent = () => {
return (
<BodyText style={styles.text} >Hi There</BodyText>
);
};
const styles = StyleSheet.create({
text: {
fontSize: 12,
color: 'blue',
fontWeight: 'bold'
},
});
export default Parent;
Interestingly when I play around in CodePen, it is displaying correctly but not on my local setup.
Implement your BodyText.js like this
import React from 'react';
import { Text, StyleSheet } from 'react-native';
const BodyText = (props) => {
const { style, children, ...rest } = props; // Destructure props here...
return (
<Text style={[styles.bodyText, style]} {...rest}>
{children}
</Text>
);
};
const styles = StyleSheet.create({
bodyText: {
fontSize: 20,
color: 'red',
},
});
export default BodyText;
Working Example Snack
You can use default props as well:
import React from "react";
import { Text, StyleSheet } from "react-native";
const BodyText = ( props ) => {
return (
<Text style={{
fontSize: props.fontSize,
color: props.color
}}>
{props.children}</Text>
);
};
BodyText.defaultProps = {
fontSize:20,
color:'red'
}
export default BodyText;
After you can use you component with new props or not:
<BodyText fontSize={12} color='blue'>Hi There</BodyText>
I have my main app with a Text, a Text Input (a component) and a button (another component):
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Alert } from 'react-native';
import { Tinput } from './components/Tinput.js';
import { Button } from './components/Button.js';
export default function App() {
return (
<View style={styles.container}>
<Text style={{fontSize:20, padding:20, textAlign:'center'}}>Ingrese un numero del pokémon a buscar!</Text>
<Tinput/>
<Button onPress={()=> ConsultarPokemon(/*this is where i want to insert the value from Tinput */)}>
Ingresar
</Button>
<StatusBar style="auto" />
</View>
);
}
And this is my component Tinput, which has the text input:
import React from 'react';
import { TextInput } from 'react-native';
const Tinput = () => {
const [numero, setNumero] = React.useState('');
return (
<TextInput
style={{ width:'90%', height: 50, borderColor: 'gray', borderWidth: 1, backgroundColor: '#fffff0', textAlign:'center', borderRadius: 20, borderWidth:5, margin:20}}
onChangeText={(value) => setNumero({numero: value})}
value={this.state.numero}
maxLength={20}
/>
);
}
export { Tinput };
I want to use the value from the text input on my onPress function, I tried doing this but didn't work:
<Button onPress={()=> ConsultarPokemon(Tinput.state.numero)}>
Ingresar
</Button>
Also, there's an error on my Tinput component: undefined is not an object (evaluating '_this.state.numero')
So I'm probably using state the wrong way too
You will use this.state.X only if you created classes like component classes , and here is an exemple :
class Counter extends React.Component {
constructor(props) {
super(props);
this.initialCount = props.initialCount || 0;
this.state = {
count: this.initialCount
}
}
increment() {
this.setState({ count: this.state.count + 1 })
}
reset() {
this.setState({ count: this.initialCount})
}
render() {
const { count } = this.state;
return (
<>
<button onClick={this.increment.bind(this)}>+1</button>
<button onClick={this.reset.bind(this)}>Reset</button>
<p>Count: {count}</p>
</>
);
}
}
I suggest to do not complicate things and just handle onPress inside Tinput
const Tinput = () => {
const [numero, setNumero] = React.useState('');
return (
<View>
<TextInput
style={{ width:'90%', height: 50, borderColor: 'gray', borderWidth: 1, backgroundColor: '#fffff0', textAlign:'center', borderRadius: 20, borderWidth:5, margin:20}}
onChangeText={(value) => setNumero(value)}
value={numero} // no need to use this.state.numero
maxLength={20}
/>
<Button onPress={()=> ConsultarPokemon(numero)}>
Ingresar
</Button>
</View>
);
}
I have a Reminder Component with a simple form comprising of one TextInput from react-native and one DatePicker from native-base and one submit to store the value on click.
I am trying to implement AyncStorage to store those values locally and later display them on another screen. But I am unable to do so, as I am getting an error 'Value is not defined.'
Whatever blog posts and tuts, the person was storing only one single property. I want to store complete state i.e input field and the date onclick of the save button.
This is my ReminderComponent
import React, { Component } from 'react';
import { View,StyleSheet, AsyncStorage, TextInput } from 'react-native';
import {
Form,
Button, Icon,
DatePicker, Text
} from 'native-base';
import PropTypes from 'prop-types';
class Reminder extends Component {
constructor(props) {
super(props);
this.state = {
input: '',
chosenDate: new Date(),
};
this.setDate = this.setDate.bind(this);
this.handleChangeInput = this.handleChangeInput.bind(this);
this.saveData = this.saveData.bind(this);
}
setDate(newDate) {
this.setState({
chosenDate: newDate
});
}
handleChangeInput = (text) => {
this.setState({input:text});
}
//On application loads, this will get the already saved data and set
//the state true when it's true.
componentDidMount() {
AsyncStorage.getItem("key").then((value) => {
this.setState({'key':value});
});
}
//save the input
saveData(value) {
console.log('value', value);
AsyncStorage.setItem("key", value);
this.setState({'key':value});
}
render() {
const {input} = this.state;
return (
<View>
<Form style={styles.formContainer}>
<View style={styles.formView}>
< TextInput
placeholder = "Set your reminder"
onChangeText={this.handleChangeInput}
value={this.state.input}
/>
<DatePicker
defaultDate={new Date()}
minimumDate={new Date(2018, 1, 1)}
maximumDate={new Date(2019, 12, 31)}
locale={"en"}
timeZoneOffsetInMinutes={undefined}
modalTransparent={false}
animationType={"fade"}
androidMode={"default"}
placeHolderText="Select date"
textStyle={{ color: "green" }}
placeHolderTextStyle={{ color: "#d3d3d3" }}
onDateChange={this.setDate}
/>
<Text style={styles.datePicker}>
{this.state.chosenDate.toString().substr(4, 12)}
</Text>
</View>
<View style={styles.footer}>
<Button block success style={styles.saveBtn}
onPress={ () =>
{this.saveData()
console.log('save data', value);}
}
>
<Icon type='MaterialIcons' name='done' />
</Button>
</View>
</Form>
</View>
);
}
}
const styles = StyleSheet.create({
formContainer: {
marginTop: 10,
padding: 10,
},
editIcon:{
color: '#28F1A6',
fontSize: 26,
},
editBtn:{
flex: 1,
alignSelf: 'flex-end',
},
datePicker:{
alignSelf: 'auto',
paddingLeft: 10
},
footer:{
position: 'relative',
top: 350
},
saveBtn: {
position:'relative',
marginTop: 35,
}
});
export default Reminder;
This is my ReminderScreen.
import React, { Component } from 'react';
import { View, StatusBar } from 'react-native';
import PropTypes from 'prop-types';
import Reminder from '../components/Reminder';
const ReminderScreen = ({navigation}) => (
<View >
<Reminder navigation={navigation} >
<StatusBar backgroundColor = "#28F1A6" />
</Reminder >
</View>
);
Reminder.propTypes = {
navigation: PropTypes.object.isRequired
}
export default ReminderScreen;
Some tweaks needed in the saveData function and get items from Asyncstorage.
While storing the data in AsyncStorage just convert entire state as a string and save it. For retrieving just convert the string to JSON object and set the value in setState function.
Please see the modified code below for Remainder component.
import React, { Component } from 'react';
import { View,StyleSheet, AsyncStorage, TextInput } from 'react-native';
import {
Form,
Button, Icon,
DatePicker, Text
} from 'native-base';
import PropTypes from 'prop-types';
class Reminder extends Component {
constructor(props) {
super(props);
this.state = {
input: '',
chosenDate: new Date(),
};
this.setDate = this.setDate.bind(this);
this.handleChangeInput = this.handleChangeInput.bind(this);
this.saveData = this.saveData.bind(this);
}
setDate(newDate) {
this.setState({
chosenDate: newDate
});
}
handleChangeInput = (text) => {
this.setState({input:text});
}
//On application loads, this will get the already saved data and set
//the state true when it's true.
componentDidMount() {
AsyncStorage.getItem("key").then((value) => {
this.setState(JSON.parse(value));
});
}
//save the input
saveData() {
AsyncStorage.setItem("key", JSON.stringify(this.state));
}
render() {
const {input} = this.state;
return (
<View>
<Form style={styles.formContainer}>
<View style={styles.formView}>
< TextInput
placeholder = "Set your reminder"
onChangeText={this.handleChangeInput}
value={this.state.input}
/>
<DatePicker
defaultDate={new Date()}
minimumDate={new Date(2018, 1, 1)}
maximumDate={new Date(2019, 12, 31)}
locale={"en"}
timeZoneOffsetInMinutes={undefined}
modalTransparent={false}
animationType={"fade"}
androidMode={"default"}
placeHolderText="Select date"
textStyle={{ color: "green" }}
placeHolderTextStyle={{ color: "#d3d3d3" }}
onDateChange={this.setDate}
/>
<Text style={styles.datePicker}>
{this.state.chosenDate.toString().substr(4, 12)}
</Text>
</View>
<View style={styles.footer}>
<Button block success style={styles.saveBtn}
onPress={ () =>
{this.saveData()
console.log('save data', value);}
}
>
<Icon type='MaterialIcons' name='done' />
</Button>
</View>
</Form>
</View>
);
}
}
const styles = StyleSheet.create({
formContainer: {
marginTop: 10,
padding: 10,
},
editIcon:{
color: '#28F1A6',
fontSize: 26,
},
editBtn:{
flex: 1,
alignSelf: 'flex-end',
},
datePicker:{
alignSelf: 'auto',
paddingLeft: 10
},
footer:{
position: 'relative',
top: 350
},
saveBtn: {
position:'relative',
marginTop: 35,
}
});
export default Reminder;