Invariant Violation: Element type is invalid: expected a string - react-native

I'm having this issue with ui kitten kit library, it works fine with regular but throw this error when I'm passing props. I tried to change my import / exports method with no luck. can please someone help figure it out.
import { RkTheme, RkButton, RkCard, RkText, rkCardContent, rkCardImg, rkCardFooter, } from 'react-native-ui-kitten';
...
export default class AutocompleteExample extends Component {
render() {
return (
<Content />
<RkCard>
<View rkCardHeader>
<Text>Header</Text>
</View>
<Image rkCardImg source={{uri: this.state.img}}/>
<View rkCardContent>
<Text>quick brown fox</Text>
</View>
<View rkCardFooter>
<Text>{this.state.price}</Text>
</View>
</RkCard>
)
}
module.exports = AutocompleteExample
this.state.img works well and I'm able to see the picture however this.state.price do not work, if replace it with a regular text it works. Thanks.

Rewriting the above code
import { RkTheme, RkButton, RkCard, RkText, rkCardContent, rkCardImg, rkCardFooter, } from 'react-native-ui-kitten';
...
export default class AutocompleteExample extends Component {
state = {
price: '',
}
render() {
return (
<Content />
<RkCard>
<View rkCardHeader>
<Text>Header</Text>
</View>
<Image rkCardImg source={{uri: this.state.img}}/>
<View rkCardContent>
<Text>quick brown fox</Text>
</View>
<View rkCardFooter>
<Text>{this.state.price}</Text>
</View>
</RkCard>
)
}
module.exports = AutocompleteExample

Related

React native onPress with TouchableWithoutFeedback is not working

I am developing a simple React Native application for learning purpose. I am just taking my initial step to get into the React Native world. But in this very early stage, I am having problems. I cannot get a simple touch event working. I am implementing touch event using TouchableWithoutFeedback. This is my code.
class AlbumList extends React.Component {
constructor(props)
{
super(props)
this.state = {
displayList : true
}
}
componentWillMount() {
this.props.fetchAlbums();
}
albumPressed(album)
{
console.log("Touch event triggered")
}
renderAlbumItem = ({item: album}) => {
return (
<TouchableWithoutFeedback onPress={this.albumPressed.bind(this)}>
<Card>
<CardSection>
<Text>{album.artist}</Text>
</CardSection>
<CardSection>
<Text>{album.title}</Text>
</CardSection>
</Card>
</TouchableWithoutFeedback>
)
}
render() {
let list;
if (this.state.displayList) {
list = <FlatList
data={this.props.albums}
renderItem={this.renderAlbumItem}
keyExtractor={(album) => album.title}
/>
}
return (
list
)
}
}
const mapStateToProps = state => {
return state.albumList;
}
const mapDispatchToProps = (dispatch, ownProps) => {
return bindActionCreators({
fetchAlbums : AlbumListActions.fetchAlbums
}, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(AlbumList);
As you can see, I am implementing touch event on the list item. But it is not triggering at all when I click on the card on Simulator. Why? How can I fix it?
You should wrap your content in component like this:
<TouchableWithoutFeedback>
<View>
<Your components...>
</View>
</TouchableWithoutFeedback>
TouchableWithoutFeedback always needs to have child View component. So a component that composes a View isn't enough.
So instead of
<TouchableWithoutFeedback onPressIn={...} onPressOut={...} onPress={...}>
<MyCustomComponent />
</TouchableWithoutFeedback>
use:
<TouchableWithoutFeedback onPressIn={...} onPressOut={...} onPress={...}>
<View>
<MyCustomComponent />
</View>
</TouchableWithoutFeedback>
See the github issue for more info
Can be used with <TouchableOpacity activeOpacity={1.0}> </TouchableOpacity>
For those who struggle with this issue in react-native 0.64, and wrapping it in just a View doesn't work, try this:
<TouchableWithoutFeedback onPress={onPress}>
<View pointerEvents="none">
<Text>Text</Text>
</View>
</TouchableWithoutFeedback>
In my case i accidentally imported TouchableWithoutFeedback from react-native-web instead of react-native. After importing from react-native everything worked as expected.
In more recent React Native versions, just use Pressable instead:
https://reactnative.dev/docs/pressable
In my case, there was a shadow underneath, which caused instability. What I did to solve it was quite simple: zIndex: 65000
<View style={{ zIndex: 65000 }}>
<TouchableWithoutFeedback onPressIn={() => {}>
<View>
</View>
</TouchableWithoutFeedback>
</View>

react native, TextInput setting onChangeText to function

I have the following component in which I am trying to set the onSubmitEditing function of a TextInput element to a custom function called func. I would like it to take the content of the TextInput box as input to the function. How can this be done? Below is my failed attempt at doing so:
export default class Component4 extends Component {
func(input){
// will add stuff here later
}
render(){
return (
<View style={{padding: 30}}>
<TextInput placeholder="default" onSubmitEditing=this.func/>
</View>
);
}
}
PS:
Thanks to everyone so far for the help, I've managed to get it working partly, here is my code now:
export default class Component4 extends Component {
constructor(props) {
super(props);
this.state = {thing: 'asdf'};
}
func(input){
this.state.thing = input;
// I will eventually do more complicated stuff here
}
render(){
return (
<View style={{padding: 30}}>
<TextInput placeholder="default" onSubmitEditing={this.func}/>
<Text>{this.state.thing}</Text>
</View>
);
}
}
this gives an error, I am trying to make it so that state.thing gets set to
the input. thanks
Option 1:
<View style={{padding: 30}}>
<TextInput placeholder="default" onSubmitEditing={this.func}/>
</View>
Option 2:
<View style={{padding: 30}}>
<TextInput placeholder="default" onSubmitEditing {(e)=>this.func(e.target.value)}/>
</View>
state={
text:''
}
Func(e){
text:e.target.value
}
onSubmitChange={this.func}
Don't forget to bind the func function

React native: Cannot add a child that doesn't have a YogaNode or parent node

Just started learning react-native,
I have created one separate file flexdemo.js and created component as below:
import React, { Component } from 'react';
import { View } from 'react-native';
export default class FlexibleViews extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: "powderblue" }}> </View>
<View style={{ flex: 2, backgroundColor: "skyblue" }}> </View>
<View style={{ flex: 3, backgroundColor: "steelblue" }}> </View>
</View>
);
}
}
and App.js file is as below:
import React, { Component } from 'react';
import {
AppRegistry,
Platform,
StyleSheet,
Text,
View, Image
} from 'react-native';
// import Bananas from './src/banana';
// import LotsOfStyles from './src/styledemo'
import FlexibleViews from './src/flexdemo';
export default class App extends Component {
render() {
return (
// <Bananas name = "Tapan"/>
<View>
<FlexibleViews />
</View>
);
}
}
That gives me this error:
Now if I try to run the code by adding flexdemo.js code into App.js then everything works fine.
Changed The App.js like this:
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
export default class FlexDimensionsBasics extends Component {
render() {
return (
// Try removing the `flex: 1` on the parent View.
// The parent will not have dimensions, so the children can't expand.
// What if you add `height: 300` instead of `flex: 1`?
<View style={{flex: 1}}>
<View style={{flex: 1, backgroundColor: 'powderblue'}} />
<View style={{flex: 2, backgroundColor: 'skyblue'}} />
<View style={{flex: 3, backgroundColor: 'steelblue'}} />
</View>
);
}
}
Remove comments inside component.
I want to give a more general answer here, because there can be several reasons for the issue returning the same error message. The three I have seen the most:
1. Comments might be the cause. But instead of removing comments make
them work:
In the return()-part, variables need to be wrapped in {} like
{this.state.foo} so wrapping the comments works fine...
return(
<Text> This works {/* it really does */}</Text>
);
...as long as they are not the first or last element in the return statement:
return(
{/* This fails */}
<Text> because the comment is in the beginning or end </Text>
{/* This also fails */}
);
2. Conditional rendering might be the cause. If myCheck is undefined or
an empty string this can fail:
const myCheck = ""; /* or const myCheck = undefined */
return(
{myCheck && <MyComponent />}
);
but adding double negation !! works:
const myCheck = ""; /* or const myCheck = undefined */
return(
{!!myCheck && <MyComponent />}
);
3. Whitespaces (or actually any strings) within a component can cause
this, if not in a <Text>-Component:
Text in a View for example:
/* This fails */
return(
<View>it really does</View>
);
But also the tiny space between two components:
/* <View>*Space*<Text> fails: */
return(
<View> <Text>it really does</Text> </View>
);
But works if in a newline:
return(
<View>
{/* This works */}
<Text>surprisingly it does</Text>
</View>
);
Unfortunately these pitfalls do not always lead to errors. Sometimes they work. I guess this depends on which of all those many tools/libraries/components you use and their versions in your app.
I was able to reproduce the issue with the code you provided. The solution is twofold:
In your flexdemo.js file you should remove the whitespaces from within the <View> tags. They are considered as text, and text is only allowed inside a <Text> component. I'd recommend making your <View> tags self closing until they have some content, to stay away from this issue in the future, like so:
import React, { Component } from 'react';
import { View } from 'react-native';
export default class FlexibleViews extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: 'powderblue' }} />
<View style={{ flex: 2, backgroundColor: 'skyblue' }} />
<View style={{ flex: 3, backgroundColor: 'steelblue' }} />
</View>
);
}
}
This will render your components but still be faulty, as you wont see anything on the screen.
To get your flexible shades of blue to appear you'll either have to add flex to the <View> component in your App.js file or(depending on what your next steps are, I guess) remove it and render your <FlexibleViews> as the root component, since it is basically a <View> component with some children anyway.
If you have if else statement in your render() function use !! like this:
{!! (this.state.your_state) &&
<View>
<Text>Your Text</Text>
</View>
}
instead of:
{(this.state.your_state) &&
<View>
<Text>Your Text</Text>
</View>
}
I downgrade react native version, then I got a different error, basically what it was I had a simple string within a view, something like this:
<View>
MyComponent
</View>
I had to wrap the string with a text component like this:
<View>
<Text>MyComponent</Text>
</View>
hope that helps
<View style={{ flex: 1 }}>
<Text style={{ flex: 1, backgroundColor: "powderblue" }}> </Text>
<Text style={{ flex: 2, backgroundColor: "skyblue" }}> </Text>
<Text style={{ flex: 3, backgroundColor: "steelblue" }}> </Text>
</View>
Make use Component hierarchy should be maintain, for example all components like Text, ListView, TextInput etc should be wrapped inside the parent component that is View.
lets see the below example :
< View >
< Text >
CORRECT
< / Text >
< / View >
Make sure all the Component tag should be closed properly.
Make sure unnecessary semicolons should be removed from the react native layout components & functions.
https://www.skptricks.com/2018/08/react-native-cannot-add-child-that.html
This error is usually from one of below mistakes
Remove unnecessary comments and remove comments from return function.
check for proper variable name.
check for unintended semicolon or any wrong syntax
Delete the comment in the return block "// "
I encountered the same problem when I accidentally add a ';' in the return block, the iOS is work well, but the Android has this bug information
In my case I had small () brackets around one of my view which was causing error.
({renderProgress()})
Removing small brackets worked for me.
{renderProgress()}
In my case I had a condition in my render function that resulted in evaluating 0.
It seems that 0 && 'some jsx' breaks in newer versions of react native.
Error Example:
render(){
return <View>
{this.state.someArray.length && <View>...</View>}
</View>
}
Although this should be valid javascript and works in react since 0 is falsey, It crashes in react native, not sure why but it works with a little refactoring as:
Working Example:
render(){
return <View>
{this.state.someArray && this.state.someArray.length> 0 &&
<View>...</View>}
</View>
}
Remove semi-colon when rendering a method in
<View style={styles.container}>
{this.renderInitialView()} //semi-color should not be here
</View>
I have encountered the same issue just now and solved it by removing the comments that I have made while editing the project in android studio and over there the comment's shorotcut just adds /* and */ but actually for react native the commented code should be enclosed with starting and end of curly braces, for example following would be an invalid comment:
/*<Text style={styles.pTop}>
{
this.state.response.map((index, value) => {
return index.title;
})
}
</Text>*/
And the following will be a valid one:
{/*<Text style={styles.pTop}>
{
this.state.response.map((index, value) => {
return index.title;
})
}
</Text>*/}
you see there is just one minor difference of enclosing the comment in curly braces.
This error also occurs if you have comments in your render() return() function. Remove all comments in your return function when rendering JSX
In my case I had written <TextInput> in the <Text> tag.
Below is wrong. It will give error for child.
<text>
<TextInput style={styles.textinput}
textcolor
placeholder = 'user id'
placeholderTextColor = 'gray'
/>
</Text>
solution.
<Text> hello </Text>
<TextInput style={styles.textinput}
textcolor
placeholder = 'user id'
placeholderTextColor = 'gray'
/>
you have to write separate tag.
So any tag you have written in another tag this error can come.

KeyboardAvoidingView - pushing up content

I am trying to use KeyboardAvoidingView (also tried a few alternatives) but it either shows the keyboard over the input field or adds a huge amount of padding between the keyboard and the input field. When I stripe the page of any other content it fairs a bit better and only adds a bit of padding between the input field and the keyboard.
Demo of the issue:
http://i.imgur.com/qoYgJpC.gifv
<KeyboardAvoidingView behavior={'position'}>
{this.state.story.image_key ?
<View style={{flex: 1}}>
<Image style={styles.storyBackgroundImage} source={{uri: this.state.story.image_url}} />
<VibrancyView
style={styles.absolute}
blurType="light"
blurAmount={25}
/>
<Image style={styles.storyImage} source={{uri: this.state.story.image_url}} />
</View>
: null
}
<View style={styles.storyContainer}>
<Text style={styles.storyTitle}>{this.state.story.title}</Text>
<Text style={styles.chapterHeader} onPress={() => navigate('User', { id: this.state.story.author.id, name: this.state.story.author.name })}>Chapter 1 by {this.state.story.author.name}</Text>
<Text style={styles.storyText}>{this.state.story.content}</Text>
{this.state.story.chapters.map(function(chapter, i) {
return <ChapterComponent chapter={chapter} key={i} navigation={() => navigate('User', { id: chapter.author.id, name: chapter.author.name })}></ChapterComponent>
})}
<WritingComponent></WritingComponent>
</View>
</KeyboardAvoidingView>
WritingComponent
import React from 'react';
import {
AppRegistry,
TextInput
} from 'react-native';
export default class WritingComponent extends React.Component {
constructor(props) {
super(props);
this.state = { text: '' };
}
render() {
return (
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
multiline={true}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
)
}
}
AppRegistry.registerComponent('WritingComponent', () => WritingComponent);
Link to code
I think the problem is the scroll view, <ScrollView style={{flex: 1}}> should be contained within your KeyboardAvoidingView Since you want this scrolling container also be resized when keyboard comes up...
set keyboardVerticalOffset="80" along with keyboardAvoidingView.
Increase/decrease 80 according to the width of your component

Button in TextInput in react native

How can I insert and style a button in text input in react native like this:
Can I use any code like this?
<Textinput>
<Button></Button>
</Textinput>
Sorry for the delay, but something like this should work:
<View style={{flexDirection:'row', width: window.width, margin: 10, padding:4, alignItems:'center', justifyContent:'center', borderWidth:4, borderColor:'#888, borderRadius:10, backgroundColor:'#fff'}}>
<View style={{flex:4}}>
<TextInput
onChangeText = {(textEntry) => {this.setState({searchText: textEntry})}}
style={{backgroundColor:'transparent'}}
onSubmitEditing = {()=>{this.onSubmit(this.state.searchText)}}
/>
</View>
<View style={{flex:1}}>
<Button onPress={ () => this.onSubmit(this.state.searchText) }>
<Image source={ require('../images/searchImage.png') } style={ { width: 50, height: 50 } } />
</Button>
</View>
</View>
where you adjust the size based on your image and Button is imported like:
import Button from '../components/Button';
I like to keep the button in an external folder, where it is like:
import React, { Component } from 'react';
import { Text, TouchableOpacity } from 'react-native';
class Button extends Component {
handlePress(e) {
if (this.props.onPress) {
this.props.onPress(e);
}
}
render() {
return (
<TouchableOpacity
onPress={ this.handlePress.bind(this) }
style={ this.props.style } >
<Text>{ this.props.children }</Text>
</TouchableOpacity>
);
}
}
export default Button;
Good luck!
wrapping both in a View with flexDirection:row should get you there.
If you want to get more advanced, you could look at the react-native-textinput-effects package that will give you some very nicely styled inputs.
<View style={{flexDirection:'row'}}>
<View>
<TextInput
style={{alignItems:'center',justifyContent:'center',backgroundColor:'white'}}
value = {this.state.searchString}
onChangeText = {(searchString) => {this.setState({searchString})}}
placeholder = 'Search'
keyboardType = 'web-search'
onSubmitEditing = {()=>{this._fetchResults()}}
ref = 'searchBar'
/>
</View>
<TouchableHighlight style={{alignItems:'center',justifyContent:'center'}} onPress = {()=>{this._fetchResults()}} underlayColor = 'transparent'>
<View>
<Icon name="search" size = {20} color = "#4285F4" />
</View>
</TouchableHighlight>
</View>
if you are not using react-native-vector-icons replace icon with .png magnifying glass image