React Native JS: Expected a component class, got [object Object] - reactjs

I have an error and really don't know why. It's a verry simple code juste for test react native, wanted to create a class who call an other class with and une a button to increment quantity :
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
TouchableHighlight,
Text,
View
} from 'react-native';
export default class Apprentissage1 extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcolm bitch
</Text>
<Product name="Product 1"/>
<Product name="Product 2"/>
</View>
);
}
}
class Product extends Component {
constructor(props) { //Constructeur
super(props);
this.state = {
quantity: 0
};
}
addToCart(){
this.setState({
quantity: this.state.quantity + 1
})
}
render(){
return(
<View style={styles.container}>
<h2>{this.props.name}</h2>
<p>Quantity: {this.state.quantity}</p>
<TouchableHighlight onPress={this.addToCart.bind(this)}>
Add To cart
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('Apprentissage1', () => Apprentissage1);
Thank's for your help :)

Replace your <h2> and <p> tags with React Native <View> component.
You cannot use DOM elements in your React Native application.

That's because you are using a non components elements like h2, p which are html elements and not react-native components.
Correct component to use for this is Text
then use Text for both h2 and p. just manipulate its fontSize to suit your needs.
<Text style={{ fontSize: 18 }}>{this.props.name}</Text>
<Text style={{ fontSize: 12}}>Quantity: {this.state.quantity}</Text>
Also ToucheableHighlight should contain a single element not a string.
<ToucheableHighlight
onPress={this.addToCart.bind(this)}
>
<Text>
Add to Cart
</Text>
</ToucheableHighlight>

I'm not sure where the error is getting triggered, but your onPress for the TouchableHighlight can just be () => { this.setState({quantity: this.state.quantity + 1}) } instead of this.bind.addToCart(this).

Separate the Product class to a new file then import it. React Native does not really like having multiple components in the same file.
Also how did you initialize the project? what is the error message?

Related

Is there a way to have a button render my camera component in React Native?

I am new to react native and am trying to make my camera component pop up whenever I click on a button. I am able to get the camera to render in App.js, but the minute I try to get it rendering in the component it just doesn't work. Should I use state to get this to render? If so, why doesn't react native allow you to just render a component within a component? I'm trying to understand the concept of components calling other components. Heres my code:
import React, {Component} from 'react';
import {Button, StyleSheet, Text, View} from 'react-native';
import DeviceCamera from './camera';
class CameraButton extends Component {
render() {
return (
<View style={styles.container}>
<Text> Button to Open Camera </Text>
<Button
onPress={() => {
<DeviceCamera />;
}}
title="click me to open the camera!"
color="#841584"
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
export default CameraButton;
I was trying to use the on press function to call the camera component but perhaps I am misunderstanding something.
Yeah, I would probably just use state here
class CameraButton extends Component {
showCamera = () => this.setState({ showCamera: true });
render() {
return (
<View style={styles.container}>
<Text> Button to Open Camera </Text>
<Button
onPress={this.showCamera}
title="click me to open the camera!"
color="#841584"
/>
{this.state.showCamera && <DeviceCamera />}
</View>
);
}
}
With JSX, you can use foo && <Bar />; if foo evaluates to something truthy, then it will render your component, otherwise it will not.

Cannot see UI in react-native for <TextInput>

I am starting with React-Native. I was able to see the <Text>. Then I progressed in adding my <TextInput>
import React from 'react';
import { StyleSheet, Text, View, TextInput } from 'react-native';
export default class App extends Component {
state = {
placeName: ''
}
placeNameChangedHandler = event => {
alert(event)
}
render(){
return (
<View style={styles.container}>
<Text>Ayman</Text>
<TextInput
style={{width:300, borderColor:"black"}}
value={this.state.placeName}
onChangeText={this.placeNameChangedHandler}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
I am able to bundle my Javascript app, but the UI shows a blank screen.
Note that I'm a novice and I'm using expo on my phone for UI device.
Add borderWidth: 1 in TextInput styles and it will show the empty textinput.

Component above react navigation's TabNavigator

I need to create a simple layout.
I have a header component and beneath it I have a navigation tabs with content (see sketch - https://imgur.com/a/9H7FMYU).
I wish to achieve this with react navigation or react native navigation.
The reason I don't want to use react-native-tab-view is because it's not maintained and have a lot of bugs.
EDIT: I just found out that React navigation uses react-native-tab-view for displaying tabs. Therefore if you are looking for a solution, either use #user:568754 answer bellow or use react-native-tab-view with a header
I think what you are looking for is the MaterialTopTabNavigator component in react-navigation.
Here is some sample code:
import React from 'react';
import { Text, View } from 'react-native';
import { createMaterialTopTabNavigator, createStackNavigator, createAppContainer } from 'react-navigation';
class Head extends React.Component {
render() {
return (
<View style={{ height: 200, backgroundColor: 'blue' }}/>
);
}
}
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
}
class SettingsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
}
const TabNavigator = createMaterialTopTabNavigator({
Home: HomeScreen,
Settings: SettingsScreen,
});
const RootNav = createAppContainer(TabNavigator);
class RootScreen extends React.Component {
render() {
return (
<View style={{ flex: 1 }}>
<Head />
<RootNav />
</View>
);
}
}
export default RootScreen;
And a link to an Expo snack to preview: https://snack.expo.io/#bra/creatematerialtoptabnavigator-example

Using a button to change the color of text

I'm trying to create a simple React Native app that:
Renders "Hello, [name]!" when a user enters a name (this part works)
Changes the "Hello, [name]!" text color when a button is pressed.
Any ideas as to how I should go about this?
I gave this an initial state of black, but that doesn't even seem to be doing anything.
What I want to happen is to trigger makeRed when the red button is clicked, which will turn the text red. Once I have this working, I'll add more color buttons.
Thank you!
See below for my App.js code. All other files were left in their default state.
import React, { Component } from 'react';
import {
AppRegistry,
Platform,
StyleSheet,
Text,
TextInput,
View,
Button
} from 'react-native';
export default class App extends Component<{}> {
constructor(props) {
super(props);
this.state = {
text: 'World',
color: 'black'
};
}
makeRed = () => {
this.setState({
color: 'red'
});
}
render() {
return (
<View style={styles.container}>
<Text style={[styles.welcome, {color: undefined}]}>
Hello, {this.state.text}!
</Text>
<TextInput
style={styles.instructions}
placeholder="Enter a name here!"
onChangeText={(text) => this.setState({text})}
/>
<Button
title='⬤'
onPress={this.makeRed}
color='red'
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 40,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
Here's a screenshot of the app for reference:
app screenshot
All you need to do is change this :
style={[styles.welcome, {color: undefined}]}
To
style={[styles.welcome, {color : this.state.color }]}
Please check : WORKING DEMO
color is not referenced as a property of state , in the style of the Text component. Try this as the Text element:
<Text style={{color: this.state.color, ...styles.welcome}}>
Hello, {this.state.text}!
</Text>
And, makeRed needs to be have it's context bound in the constructor, or else this.setState will be undefined. Like this (under super(props)):
this.makeRed = this.makeRed.bind(this)

How to add stateless component to a touchable component

I am trying to add a stateless component to my button.
const button = ({onButtonPress, buttonText}) => {
return (
<TouchableHighlight
onPress={() => onButtonPress()}>
<ButtonContent text={buttonText}/>
</TouchableHighlight>
)
};
and get this error:
Warning: Stateless function components cannot be given refs (See ref "childRef"
in StatelessComponent created by TouchableHighlight).
Attempts to access this ref will fail.
I have read up on the issue but I am still new to javascript and RN and have not found a solution. Any help would be appreciated.
full code:
GlossaryButtonContent:
import React from 'react';
import {
View,
Text,
Image,
StyleSheet
} from 'react-native';
import Colours from '../constants/Colours';
import {
arrowForwardDark,
starDarkFill
} from '../assets/icons';
type Props = {
text: string,
showFavButton?: boolean
}
export default ({text, showFavButton} : Props) => {
return (
<View style={styles.container}>
{showFavButton &&
<Image
style={styles.star}
source={starDarkFill}/>}
<Text style={[styles.text, showFavButton && styles.favButton]}>
{showFavButton ? 'Favourites' : text}
</Text>
<Image
style={styles.image}
source={arrowForwardDark}
opacity={showFavButton ? .5 : 1}/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'center'
},
favButton: {
marginLeft: 10,
color: Colours.darkTextHalf
},
text: {
flex: 1,
paddingTop: 5,
marginLeft: 20,
fontFamily: 'Bariol-Bold',
fontSize: 24,
color: Colours.darkText
},
image: {
marginRight: 20
},
star: {
marginLeft: 10
}
});
GlossaryButton:
import React from 'react';
import {
TouchableHighlight,
StyleSheet
} from 'react-native';
import Colours from '../constants/Colours';
import ShadowedBox from './ShadowedBox';
import GlossaryButtonContent from './GlossaryButtonContent';
type Props = {
buttonText: string,
onButtonPress: Function,
rowID: number,
sectionID?: string,
showFavButton?: boolean
}
export default ({buttonText, onButtonPress, rowID, sectionID, showFavButton} : Props) => {
return (
<ShadowedBox
style={styles.container}
backColor={showFavButton && Colours.yellow}>
<TouchableHighlight
style={styles.button}
underlayColor={Colours.green}
onPress={() => onButtonPress(rowID, sectionID)}>
<GlossaryButtonContent
text={buttonText}
showFavButton={showFavButton}/>
</TouchableHighlight>
</ShadowedBox>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
height: 60,
marginBottom: 10,
borderRadius: 5
},
button: {
flex: 1,
borderRadius: 5
}
});
Basically, Stateless components cannot have refs.
So, having a stateless component in the middle of the render tree will create a void in the ref chain, meaning you cannot access lower-down components.
So, the problem comes from trying to do this:
let Stateless = (props) => (
<div />
);
let Wrapper = React.createClass({
render() {
return <Stateless ref="stateeee" />
}
});
TouchableHighlight needs to give a ref to its child. And this triggers that warning.
Answer:
You can't actually make a stateless component a child of TouchableHighlight
Solution:
Use createClass or class to create the child of TouchableHighlight, that is GlossaryButtonContent.
See this github issue for more info and this one

Resources