How to add multiple components in React Native? - javascript

Note: I am new to React Native and have searched up how to do this but found no helpful results I am using React Native to create an app and want to add multiple components, such as text, buttons, and a text input space, but am having trouble doing so without receiving errors. Is there any way to include multiple components into one javascript document using React Native?
The code I currently have:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={{alignItems: 'center'}}>
<Text style={styles.bigblack}>Sample Bold Text Here</Text>
<Text>Sample Text Here:</Text>
</View>
);
}
}
const styles = StyleSheet.create({
bigblack: {
color: 'black',
fontWeight: 'bold',
fontSize: 28,
},
red: {
color: 'red',
},
container: {
flex: 1,
backgroundColor: '#fdf5e6',
alignItems: 'center',
justifyContent: 'center',
},
});
Code I want to add for Text Input:
class UselessTextInput extends Component {
render() {
return (
<TextInput
{...this.props}
editable = {true}
maxLength = {40}
/>
);
}
}
export default class UselessTextInputMultiline extends Component {
constructor(props) {
super(props);
this.state = {
text: 'Useless Multiline Placeholder',
};
}
render() {
return (
<View style={{
backgroundColor: this.state.text,
borderBottomColor: '#000000',
borderBottomWidth: 1 }}
>
<UselessTextInput
multiline = {true}
numberOfLines = {4}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
</View>
);
}
}
Code I want to add for Button:
<Button
onPress={onPressLearnMore}
title="Learn More"
color="#841584"
accessibilityLabel="Learn more about this button"
/>

You can create multiple component in same document but can export default only one.
So you can create multiple component like below:
export class UselessTextInput {}
export class UselessTextInputMultiline {}
export class Button {}
while accessing :
import {UselessTextInput, UselessTextInputMultiline, Button} from './components/customInput' // change with your respective path
if you still want to have single export default then:
export default class UselessTextInputMultiline {}
and while importing
import Template,{Button} from './components/customInput'
For, exporting multiple component:
module.exports = {
text: UselessTextInput,
btn: Button
}
imports will be like:
let txtInput= require('./components/customInput').text;
let btnInput = require('./components/customInput').btn;

Related

React native View' cannot be used as a JSX component. Its instance type 'View' is not a valid JSX element

I´am currently getting the following error on the View component inside App.tsx: 'View' cannot be used as a JSX component. Its instance type 'View' is not a valid JSX element
I think the issue is related to the library
import React from 'react';
import {View,Text,StyleSheet, Button} from 'react-native'
import {createSwitchNavigator} from 'react-navigation'
const styles = StyleSheet.create({
txt:{
fontSize: 48
},
view: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
})
class screenComponent1 extends React.Component {
render() {
return(
<View>
<Button onPress={() => this.props.navigation.navigate('screenroute2')} title='next page'/>
</View>
)
}
}
class screenComponent2 extends React.Component {
render() {
return(
<View>
<Button onPress={() => this.props.navigation.navigate('screenroute1')} title='next page'/>
</View>
)
}
}
const AppNavigator = createSwitchNavigator({
screenroute1: screenComponent1,
screenroute2: screenComponent2,
})
export default class App extends React.Component {
render() {
return <AppNavigator/>
}
}

React native dynamic render

I'm trying to make a custom router component, that will pick a layout dynamically. But, when I'm trying to render layout dynamically I receive blank page.
What I'm doing wrong?
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import WelcomePageLayout from '../layouts/welcome-page';
import GamePageLayout from '../layouts/game';
export default class Router extends Component {
constructor(props) {
super(props);
this.layouts = [
WelcomePageLayout,
GamePageLayout
];
this.state = {
currentLayout: 0
};
}
render() {
const layout = this.layouts[this.state.currentLayout];
return (
<View style={styles.container}>
{ layout }
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
flex: 1,
paddingTop: 60,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 100
}
});
A step ago, before adding this dynamic render everything was working as expected. So I'm pretty sure it's something about that.
Thanks in advance.
You are just passing the component as a child to View. Make sure you render it as well:
render() {
const Layout = this.layouts[this.state.currentLayout];
return (
<View style={styles.container}>
<Layout />
</View>
);
}

how get values of components react native

I want to get the value of the email and passowrd in my Form.js, so that click click button can pass them a client api
1. this is my class src/components/login/Form.js
import React, { Component } from 'react';
import {
KeyboardAvoidingView,
StyleSheet,
TouchableHighlight,
Image,
} from 'react-native';
import UserInput from "./UserInput";
import usernameImg from '../../images/Iconperson.png';
import passwordImg from '../../images/Iconlock.png';
import eyeImg from '../../images/eye.png';
export default class Form extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
};
}
_onPress() {
console.warn("email", this.state.email)
console.warn("password", this.state.password)
}
render() {
return (
<KeyboardAvoidingView behavior='padding'
style={styles.container}>
<UserInput source={usernameImg}
onChangeText = {(email) => this.setState({email})}
keyboardType = 'email-address'
placeholder='Username'
autoCapitalize={'none'}
returnKeyType={'done'}
autoCorrect={false} />
<UserInput source={passwordImg}
onChangeText = {(password) => this.setState({password})}
placeholder='Password'
returnKeyType={'done'}
autoCapitalize={'none'}
autoCorrect={false} />
<TouchableHighlight
onPress={this._onPress}
activeOpacity={1} >
<Text>LOGIN</Text>
</TouchableHighlight>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
}
});
2. this is my class src/components/login/UserInput.js
import React, { Component , PropTypes} from 'react';
import Dimensions from 'Dimensions';
import {
StyleSheet,
View,
TextInput,
Image,
} from 'react-native';
const DEVICE_WIDTH = Dimensions.get('window').width;
const DEVICE_HEIGHT = Dimensions.get('window').height;
export default class UserInput extends Component {
render() {
return (
<View style={styles.inputWrapper}>
<Image source={this.props.source}
style={styles.inlineImg} />
<TextInput style={styles.input}
onChangeText = {(this.props.ChangeText) =>
this.setState({field})}
placeholder={this.props.placeholder}
secureTextEntry={this.props.secureTextEntry}
autoCorrect={this.props.autoCorrect}
autoCapitalize={this.props.autoCapitalize}
returnKeyType={this.props.returnKeyType}
placeholderTextColor='white'
keyboardType ={this.props.keyboardType}
underlineColorAndroid='transparent' />
</View>
);
}
}
UserInput.propTypes = {
ChangeText : PropTypes.string,
source: PropTypes.number.isRequired,
placeholder: PropTypes.string.isRequired,
keyboardType : PropTypes.string,
secureTextEntry: PropTypes.bool,
autoCorrect: PropTypes.bool,
autoCapitalize: PropTypes.string,
returnKeyType: PropTypes.string,
};
const styles = StyleSheet.create({
input: {
backgroundColor: 'rgba(255, 255, 255, 0.2)',
width: DEVICE_WIDTH - 40,
height: 40,
marginHorizontal: 20,
paddingLeft: 45,
borderRadius: 20,
color: '#ffffff',
},
inputWrapper: {
flex: 1,
},
inlineImg: {
position: 'absolute',
zIndex: 99,
width: 22,
height: 22,
left: 35,
top: 9,
},
});
As you are typing into the TextInput I see you are trying to change the state in the Form component. For this to happen correctly, setState needs to be called from the Form component. There are a couple functions currently being passed down through props:
(email) => this.setState({email})
// and
(password) => this.setState({password})
Looking at how those are being used in your UserInput component, whenever a new character is added to that text box, invoke the function above. so when this.setState() is called, it is saying UserInput.setState(). Since we want to change the state in Form we have to bind those functions to the parent component.
Instead of passing the functions directly to props, let's add some user methods:
export default class Form extends Component {
constructor(props) {}
_onChangeEmail(email) {
this.setState(Object.assign({}, state, { email })); // good practice for immutability
}
_onChangePassword(password) {
this.setState(Object.assign({}, state, { password })); // good practice for immutability
}
render() {}
}
Next, we need to bind these class methods to itself. That way no matter where these are called, this will always point to the Form component. This is most commonly done in the constructor:
export default class Form extends Component {
constructor(props) {
super(props)
this.state = {}
// this is where we do the binding
this._onChangeEmail = this._onChangeEmail.bind(this)
this._onChangePassword = this._onChangePassword.bind(this)
}
_onChangeEmail(email) { /* code */}
_onChangePassword(password) { /* code */}
render() {}
}
Now pass these down to the UserInput component through props:
// Form.js
render() {
return (
<KeyboardAvoidingView>
<UserInput onChangeText={this._onChangeEmail} />
<UserInput onChangeText={this._onChangePassword} />
</KeyboardAvoidingView>
)
}
These methods should now be used when the user inputs text:
export default class UserInput extends Component {
render() {
return (
<View>
<Image />
<TextInput onChangeText = {this.props.onChangeText} />
</View>
);
}
}
Bonus: You also should add a property 'value' to the text input:
export default class UserInput extends Component {
render() {
return (
<View>
<Image />
<TextInput
onChangeText={this.props.onChangeText} />
value={this.props.textValue}
</View>
);
}
}
And make sure it is passed down from the parent component:
// Form.js
render() {
return (
<KeyboardAvoidingView>
<UserInput
onChangeText={this._onChangeEmail}
textValue={this.state.email}/>
<UserInput
onChangeText={this._onChangePassword}
textValue={this.state.password}/>
</KeyboardAvoidingView>
)
}
The value of TextInput may be retrieved through its _lastNativeTextproperty.
this.refs.myTextInput._lastNativeText
See this answer

React Native multiline, value, smaller than placeholder in TextInput component

When adding text into a <TextInput> component with multiline set to false the value text matches the placeholder text font size, whereas if multiline is equal to true, the value text font size is smaller than the placeholder font size.
Is this a normal behaviour or a bug?
Edit:
/* #flow */
import React from 'react'
import Separator from './components/Separator'
import {Button, StyleSheet, TextInput, View} from 'react-native'
const styles = StyleSheet.create({
subject: {
height: 20,
},
body: {
height: 100,
},
})
export default class NewQuestion extends React.Component {
static navigationOptions = ({navigation}) => ({
title: 'AIBU',
headerLeft: (
<Button
onPress={() => {
navigation.goBack()
}}
title="Back"
/>
),
})
state = {
subject: '',
body: '',
}
render() {
return (
<View>
<TextInput
autoFocus
onChangeText={subject => this.setState({subject})}
placeholder="Enter your AIBU subject..."
style={styles.subject}
value={this.state.subject}
/>
<Separator />
<TextInput
multiline
onChangeText={body => this.setState({body})}
placeholder="Enter your AIBU description..."
style={styles.body}
value={this.state.body}
/>
</View>
)
}
}
As far as I see, the default font size is actually different for multiline and non-multiline TextInput-s. One way to handle this is by introducing another component which acts as an abstraction on top of TextInput:
const styles = StyleSheet.create({
text: {
fontFamily: 'System',
fontStyle: 'normal',
fontSize: 20,
lineHeight: 20,
letterSpacing: 0.6
}
})
export default class AppTextInput extends Component {
static propTypes = {
style: TextInput.propTypes.style
}
static defaultProps = {
style: {}
}
render() {
return (
<TextInput
{...this.props}
style={[
styles.text,
this.props.style
]}
/>
)
}
}
Now you can just use AppTextInput the same way TextInput is supposed to be used, and all issues related to styling inputs are covered in a single place.

React Native Tabbar iOS binding issue [Expected a component class, got object Object]

I've got a simple React Native app with a TabBarIOS component.
For each tab, I have a seperate .js file and the main TabBarIOS component lives in index.ios.js. The other classes are home.ios.js and contact.ios.js.
After I click on an icon I want the app to show the corresponding page( home.ios.js or contact.ios.js). However when I click one of the icons, I get a "Expected a component class, got object Object" error.
So far it looks like the rendering of the TabBarIOS component is alright. I myself think that there is a problem in the binding with the other .js files or a problem with the injection.
index.ios.js
var React = require('react');
var ReactNative = require('react-native');
import Home from './home.ios';
import Contact from './contact.ios';
var {
AppRegistry,
TabBarIOS,
} = ReactNative;
var {
Component
} = React;
class Tab extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'Home'
};
}
render() {
return (
<TabBarIOS selectedTab={this.state.selectedTab}>
<TabBarIOS.Item
selected={this.state.selectedTab === 'Home'}
systemIcon="featured"
onPress={() => {
this.setState({
selectedTab: 'Home',
});
}}>
<home/>
</TabBarIOS.Item>
<TabBarIOS.Item
selected={this.state.selectedTab === 'Contact'}
systemIcon="contacts"
onPress={() => {
this.setState({
selectedTab: 'Contact',
});
}}>
<contact/>
</TabBarIOS.Item>
</TabBarIOS>
)
}
}
AppRegistry.registerComponent('ProtoReactNative', () => Tab);
home.ios.js (I include only this one, contact.ios.js looks the same)
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
StyleSheet,
View,
Text
} = ReactNative;
var {
Component
} = React;
var styles = StyleSheet.create({
description: {
fontSize: 20,
textAlign: 'center',
color: '#FFFFFF'
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'blue',
}
});
class Home extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.description}>
Welcome to your React Native Start Component!
</Text>
</View>
);
}
}
module.exports = Home;
Hopefully someone has a solution for me!
Thanks in advance!
EDIT:
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
StyleSheet,
} = ReactNative;
var {
View,
Text,
Component
} = React;
var styles = StyleSheet.create({
description: {
fontSize: 20,
textAlign: 'center',
color: '#FFFFFF'
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'red',
}
});
class Contact extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.description}>
This could be your second tab
</Text>
</View>
);
}
}
module.exports = Contact;
Step 1: Change <home/> to <Home/> and <contact/> to <Contact/>
Step 2: Inside contact js file, View and Text should be imported from ReactNative. Currently its imported from React

Categories