React-Native: Element type is invalid - react-native

I have problem with nativebase Footer
I have Container and if I include MyFooter, it give me this error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in.
// main.js
import MyFooter from './MyFooter';
...
<Container>
<MyHeader title="Оплаты" />
<Content></Content>
<MyFooter />
</Container>
And Footer component
// MyFooter.js
const MyFooter = props => {
return (
<Footer>
<FooterTab>
<Button vertical active>
<Text>Info</Text>
</Button>
<Button vertical >
<Text>Remove</Text>
</Button>
</FooterTab>
</Footer>
);
}
export default MyFooter;
But if I change render method of MyFooter like this:
// MyFooter.js
return (
<View>
<Text>
Test
</Text>
</View>
)
So problem not in export/import, because with another render in MyFooter all work perfectly.
Can anybody help with this, please?
Answer - import { Text, Footer, FooterTab, Button, Icon } from 'react-native'; ('react-native' instead 'native-base')

Is this your MyFooter component try to export your component first export default MyFooter like these following:
const MyFooter = () => (
<Footer>
<FooterTab>
<Button vertical active>
<Icon name="information" />
<Text>Инфо</Text>
</Button>
<Button vertical >
<Icon name="add" />
<Text>Оплаты</Text>
</Button>
<Button vertical >
<Icon name="remove" />
<Text>Снятия</Text>
</Button>
</FooterTab>
</Footer>
);
export default MyFooter;

If you pasted your code exactly as is, then you're missing your closing brace after your return statement in MyFooter.js

Related

React Native: Element Type is invalid Exspecting a String

import {CITYIMG} from '../assets/index';
export default class Login extends Component {
render() {
return (
<Container>
<Image source = {CITYIMG}/>
<Card style={styles.card}>
<Text>
Sign In
</Text>
<Item rounded>
<Input placeholder='Username'/>
</Item>
<Item rounded>
<Input placeholder='Password'/>
</Item>
<Button hasText transparent>
<Text>Forgot Password</Text>
</Button>
<Button rounded>
<Text>Login</Text>
</Button>
<Button rounded>
<Text>Sign Up</Text>
</Button>
</Card>
</Container>
);
}
}
I am exporting images in another folder and get the error:
Expected String or a class function but got undefined . You likely forgot to export your component from the file its defined in.
export const CITYIMG = require('./cityimg.jpg');
for having static images you need to have source={require("../Path/To/picture.extention")}
and you need to require them when you want to use it in the same file(not by exporting and importing)

Native-base Invariant Violation: Text strings must be rendered within a Text Component

I am getting this error with my code:
export default class AddExpensePage extends Component {
render() {
return (
<Container>
<Header>
<Title>Add Expense</Title>
</Header>
<Content>
<InputGroup borderType='underline' >
<Input placeholder='Item Name' />
</InputGroup>
<Button primary> Testing </Button>
</Content>
</Container>
);
}
}
And this is the code on their official documentation:
export default class ButtonExample extends Component {
render() {
return (
<Container>
<Content>
// NativeBase default style
<Button> Click Me! </Button>
</Content>
</Container>
);
}
}
I don't get why I have this error because supposedly I do not have to wrap the text "Testing" in Text tags?
You have to wrap in Text tag like:
<Content>
<Button>
<Text>Click Me!</Text>
</Button>
</Content>
DOC

Changing segment content onPress

I have segments and I want them to act as tabs. I tried using react-navigation onPress of each segment but it doesn't look nice.
I want the segments to stay fixed at the top and on clicking each one the content should change or call a specific component without reloading or noticing that the screen has changed.
<Segment>
<Button first>
<Text>Puppies</Text>
</Button>
<Button>
<Text>Kittens</Text>
</Button>
<Button last active>
<Text>Cubs</Text>
</Button>
</Segment>
<Content>
<Text>Awesome segment</Text>
</Content>
Segments can be customized as a react-navigation single screen separated into multiple components which can be rendered on demand.
Example
(Using native-base components)
state = {
activePage:1,
}
selectComponent = (activePage) => () => this.setState({activePage})
_renderComponent = () => {
if(this.state.activePage === 1)
return <Component1/> //... Your Component 1 to display
else
return <Component2/> //... Your Component 2 to display
}
render() {
return (
<Container>
<Header>
<Left />
<Body>
<Segment>
<Button active={this.state.activePage === 1}
onPress={this.selectComponent(1)}><Text>Component 1</Text></Button>
<Button active={this.state.activePage === 2}
onPress= {this.selectComponent(2)}><Text>Component 2</Text></Button>
</Segment>
</Body>
<Right/>
</Header>
<Content padder>
{this._renderComponent()}
</Content>
</Container>
)
}
You can customize it to add more components based on the conditions set above
Edit
Supposing you navigate to a particular screen that also contains Segment, the on some item button click you can do
this.props.navigation.navigate('OtherSegmentScreen', {activePage: this.state.activePage})
And on that page receive the props as
const {navigate} = this.props.navigation
const previousActiveSegment = navigate.getParams('activePage', '1') //... 1 is default value that you can set

How to pass a already implemented Component inside the Copilot Step in react-native-copilot

I am trying to built a guided tour for my app using react native copilot
https://github.com/okgrow/react-native-copilot
and i cannot figure out how to use a already built component inside the its CopilotSteps as mentioned in the tutorial.
This is the my code so far and it gives me the following error
<CopilotStep
text="This is a hello world example!"
order={1}
name="hello"
>
{({ copilot }) => (
<Card snow to={`${basePath}/account`} {...copilot}>
<Row inline justify="center" fluid>
<Block inline justify="center">
<FIcon name="shield" size={25} />
</Block>
<Block justify="center">
<P compact>Account and Security</P>
<P compact small helper>
Edit Your Account Information
</P>
</Block>
<Block inline justify="center">
<FIcon name="chevron-right" size={25} />
</Block>
</Row>
</Card>
)}
</CopilotStep>
error =>
D:\My Work\Company Projects\Ongoing\ZappyFoods\Mobile App\zappyfood_app\node_modules\react-native\Libraries\Core\ExceptionsManager.js:63 Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
what should i do to get this code run proerly
You have to make the component "walkthroughable", so for example if my original component was a simple TouchableOpacity button.
<TouchableOpacity
onPress={this.callFunction}
>
<Icon name="photo" type="FontAwesome" />
</TouchableOpacity>
Then to make it work with copilot first import walkthroughable.
import {
copilot,
walkthroughable,
CopilotStep
} from "#okgrow/react-native-copilot";
Then call the walkthroughable function passing our TouchableOpacity component.
const WalkthroughableTouchableOpacity = walkthroughable(TouchableOpacity);
Finally add the copilot step and use the new Walkthroughable component in place where you would've used TouchableOpacity.
<CopilotStep
text="Hey! This is the first step of the tour!"
order={1}
name="openApp"
>
<WalkthroughableTouchableOpacity
onPress={this.callFunction}
>
<Icon name="photo" type="FontAwesome" />
</WalkthroughableTouchableOpacity>
</CopilotStep>
So the entire file could look like
import {
copilot,
walkthroughable,
CopilotStep
} from "#okgrow/react-native-copilot";
import { Icon } from "native-base";
import React, { Component } from "react";
import { TouchableOpacity } from "react-native";
const WalkthroughableTouchableOpacity = walkthroughable(TouchableOpacity);
class Example extends Component {
componentDidMount = async () => {
this.props.copilotEvents.on("stepChange", () => {});
this.props.start();
};
callFunction = () => {
console.log("Button Pressed.");
};
render() {
return (
<CopilotStep
text="Hey! This is the first step of the tour!"
order={1}
name="openApp"
>
<WalkthroughableTouchableOpacity onPress={this.callFunction}>
<Icon name="photo" type="FontAwesome" />
</WalkthroughableTouchableOpacity>
</CopilotStep>
);
}
}
export default copilot({
animated: true,
overlay: "svg"
})(Example);

Implementing Footer Tabs in Native React using Native Base

I am creating a native react application using native base for the UI (http://nativebase.io/docs/v2.0.0/components#footerTab). I am using the footerTabs component and my code is as follows
render() {
return (
<Container>
<Header backgroundColor="#ECEFF1">
<Button transparent>
<Icon name='ios-menu' style={{color: 'black'}}/>
</Button>
<Title style={{color:'black'}}>Header</Title>
</Header>
<Content>
<Profile/>
</Content>
<Footer backgroundColor="#212121">
<FooterTab>
<Button backgroundColor="#000" >
<Icon name="ios-person" size={30} color="#900"/>
<Text>Profile</Text>
</Button>
<Button>
<Icon name="ios-search"/>
<Text>Search</Text>
</Button>
<Button>
<Icon name="ios-camera"/>
<Text>Camera</Text>
</Button>
<Button>
<Icon name="ios-apps"/>
<Text>Apps</Text>
</Button>
<Button>
<Icon active name="ios-navigate"/>
<Text>Navigate</Text>
</Button>
</FooterTab>
</Footer>
</Container>
);
}
I have created different JS files for different functionalities such as Profiles,Search,Apps ect.. and have imported them as follows.
import Profile from './Profile';
How do I implement the onPress functionality on the buttons of the footer to change the component in the content tag depending on what was selected?
<Content>
<Profile/>
</Content>
For eg: If I pressed the search button I want the profile tag to be replaced with and similarly the same for the other buttons.
Here FooterTab from native base is not persist actual tab functionality like UITabBar in iOS, its only persist for design. What you need to do is, keep footer tag in all of your component with all four buttons and keep active accordingly. For changing view by selecting any button you need to replace current view by selected one using navigator like:
<Button onPress={()=> { this.props.navigator.replace({id:'component name'}) }}>
and in your navigator component you should define all required components in renderScene method on the basis of id value in route payload. If you want actual functionality as TabBar work then you can use this third party module react-native-tab-navigator. Thanks!
Instead of replacing the content, why don't you have each Button navigate to a new page?
Let's say you're on the Profile tab. You could do something like this:
import FooterWrapper from './FooterWrapper'
<Footer>
<FooterWrapper tab='profile' navigator={this.props.navigator} />
</Footer>
And then in your FooterWrapper (I just handled a case of two tabs):
constructor(props) {
super(props)
this.state = {
profileTab: this.props.tab === 'profile',
searchTab: this.props.tab === 'search',
}
}
navToProfilePage() {
this.props.navigator.push({
id: 'profile',
tab: 'profile',
})
}
navToSearchPage() {
this.props.navigator.push({
id: 'search',
tab: 'search',
})
}
render() {
return (
<FooterTab>
<Button active={this.state.profileTab} onPress={() => this.navToProfilePage()}>
Profile
<Icon name='ios-person' size={30} color='#900' />
</Button>
<Button active={this.state.searchTab} onPress={() => this.navToSearchPage()}>
Search
<Icon name='ios-search' />
</Button>
</FooterTab>
)
}
Ok so here is I how got it I used the renderContent method within the content tags to generate views depending on the state change when the button was clicked.
<Content>
{this._renderContent(this.state.selectedTab)}
</Content>
The selectedTab is a state variable whose state is set using this.setState in the onPress method. The renderContent has an if function that checks the selected tab and returns the appropriate view. I also tried the navigation approach but this seemed cleaner.
_renderContent = (Tab: string,) => {
if(this.state.selectedTab==="Profile"){
return (
<Profile/>
);
}
else if(this.state.selectedTab==="Search"){
}
}