Module Error Requiring unknown module - reactjs

Hello am having a problem I am using react native am a newbie and I am creating a app that has some tabs but what i want is when i click the tab each as its own navigation bar.
I follow [AppCoda Example][1] but i notice that code base is different from the new code base react native. my code is bellow. Remember am trying to get a Nav bar for each tabs an i created a folder structure to require each tab in but am getting that unknown module when i know its there. Just to add if i add the same code which was in sub folder in the index.os.js it works look below:
'use strict';
var React = require('react-native');
var SearchButton = require('./app/components/buttons/searchButton');
var CameraButton = require('./app/components/buttons/cameraButton');
var ProfileButton = require('./app/components/buttons/profileButton');
var ContactButton = require('./app/components/buttons/contactButton');
var {
AppRegistry,
TabBarIOS,
NavigatorIOS,
StyleSheet,
Text,
View
} = React;
class AwesomeProject extends React.Component{
constructor(props) {
super(props);
this.state = {
selectedTab: 'Search'
};
}
render() {
return (
<TabBarIOS selectedTab={this.state.selectedTab} barTintColor="darkslateblue">
<TabBarIOS.Item
selected={this.state.selectedTab === 'Search'}
systemIcon="search"
onPress={() => {
this.setState({
selectedTab: 'Search'
});
}} style={styles.container} >
<SearchButton/>
</TabBarIOS.Item>
<TabBarIOS.Item systemIcon="bookmarks"
selected={this.state.selectedTab === 'Camera'}
icon={{uri:'Camera'}}
onPress={() => {
this.setState({
selectedTab: 'Camera'
});
}}>
<CameraButton/>
</TabBarIOS.Item>
<TabBarIOS.Item systemIcon="history"
selected={this.state.selectedTab === 'Profile'}
icon={{uri:'Profile'}}
onPress={() => {
this.setState({
selectedTab: 'Profile'
});
}}>
<ProfileButton/>
</TabBarIOS.Item>
<TabBarIOS.Item systemIcon="contacts"
selected={this.state.selectedTab === 'Contacts'}
icon={{uri:'Contacts'}}
onPress={() => {
this.setState({
selectedTab: 'Contacts'
});
}}>
<ContactButton/>
</TabBarIOS.Item>
</TabBarIOS>
);
}
};
var styles = StyleSheet.create({
navigator: {
flex: 1,
},
tabContent: {
flex: 1,
alignItems: 'center', },
tabText: {
color: 'white',
margin: 50, },
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('AwesomeProject', () => AwesomeProject);
Now in the search button which should get the search title from a navigation folder thats where the problem is its saying unknown module
'use strict';
var React = require('react-native');
var searchTitle = require('./app/components/navigation/searchTitle');
var {
StyleSheet,
View,
NavigatorIOS,
Text
} = React
var styles = StyleSheet.create({
navigator: {
flex: 1
}
}
);
class Search extends React.Component{
render() {
return (
<NavigatorIOS
style={styles.navigator}
initialRoute={{
title: 'SomeTitle',
component: searchTitle
}}/>
);
}
}
module.exports = Search;
can some one help me with this.

You are asking require to search a relative path. From your examples I see that searchButton is in ./app/components/buttons/ and searchTitle is in ./app/components/navigation/, so if you want to require searchTitle from searchButton the path you need to specify is ../navigation/searchTitle.

var back_bg = require('./../img/menu.png');

Related

Uploading an image in react-native using react-native-image-picker

I have just initialized a basic react-native project and its running in the emulator. I have as well installed this package https://github.com/react-community/react-native-image-picker
and i am trying to upload an image. The code is simple as i have just added some code to handle image upload
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Button,
Text,
Image,
Alert,
View
} from 'react-native';
var ImagePicker = require('react-native-image-picker');
var options = {
title: 'Select Avatar',
customButtons: [
{name: 'fb', title: 'Choose Photo from Facebook'},
],
storageOptions: {
skipBackup: true,
path: 'images'
}
};
const onPressLearnMore = () => {
ImagePicker.launchImageLibrary(options, (response) => {
let source = { uri: response.uri };
this.setState({
avatarSource: source
});
});
//Alert.alert('Button has been pressed!');
};
export default class AwesomeProject extends Component {
constructor() {
super()
this.state = {
avatarSource: 'image.jpg'
}
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Button onPress={onPressLearnMore} title="Upload Image" color="#841584" accessibilityLabel="Learn more about this purple button" />
<Image source={this.state.avatarSource} style={styles.uploadAvatar} />
</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('AwesomeProject', () => AwesomeProject);
I get this error when i run this on the emulator
undefined is not a function (evaluating '_this.setState({
avatarSource: source
})')
<unknown>
index.android.bundle?platform=android&dev=true&hot=false&minify=false:1274:19
__invokeCallback
index.android.bundle?platform=android&dev=true&hot=false&minify=false:4818:21
<unknown>
index.android.bundle?platform=android&dev=true&hot=false&minify=false:4664:32
__guard
index.android.bundle?platform=android&dev=true&hot=false&minify=false:4753:11
invokeCallbackAndReturnFlushedQueue
index.android.bundle?platform=android&dev=true&hot=false&minify=false:4663:19
You should write the function onPressLearnMore inside your AwesomeProject component, and don't forget to bind in order to use this
export default class AwesomeProject extends Component {
constructor(){
...
this.onPressLearnMore = this.onPressLearnMore.bind(this)
}
onPressLearnMore(){
//you can use this.setState
}
render(){
...
}
}

React-Native - undefined is not an object" (evaluating 'this.state.*) _renderRow

I am trying to call the state inside the _renderRow() function but I keep receiving the following error:
This is my source code:
Source code
var Store = require('./store/Store.js');
var MessageOptions = require('./MessageOptions.js')
var React = require('react');
var ReactNative = require('react-native');
var {
AppRegistry,
Image,
ListView,
StyleSheet,
Text,
View,
} = ReactNative;
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedRowID: 20,
dataSource: ds
}
}
componentWillMount() {
this.getNewMessages();
}
getNewMessages() {
Store.getMessages().then((messages) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(messages)
});
},(reason) => {
console.log("Error:", reason);
});
}
_renderRow(rowData: string, sectionID: number, rowID: number, highlightRow: (sectionID: number, rowID: number) => void) {
var currentSelectedRowID = this.state.selectedRowID;
return (
<View>
<View style={styles.row}>
<Image style={styles.thumb} source={require('../android/app/src/main/res/mipmap-hdpi/ic_launcher.png')} />
<Text style={styles.text}>
{rowData.text}
</Text>
</View>
<MessageOptions optionsData={rowData.options} message_uri={rowData.uri}/>
</View>
)
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow}
/>
)
}
};
var styles = StyleSheet.create({
row: {
flexDirection: 'row',
justifyContent: 'center',
padding: 10,
backgroundColor: 'white',
},
thumb: {
width: 64,
height: 64,
},
text: {
flex: 1,
},
news_item: {
paddingLeft: 10,
paddingRight: 10,
paddingTop: 15,
paddingBottom: 15,
marginBottom: 5
},
news_item_text: {
color: '#575757',
fontSize: 18
}
});
module.exports = Application;
The error is coming from the _renderRow method where I am storing this.state.selectedRowID to the var currentSelectedRowID.
Thanks in advance.
Solution
The problem was with my ES6 class constructor:
class Application extends React.Component {
constructor(props) {
super(props);
this._renderRow = this._renderRow.bind(this);
this.state = {
selectedRowID: 20,
dataSource: ds
}
}
The solution was to add the following line to my constructor:
this._renderRow = this._renderRow.bind(this);

How to jump to another view on or before render?

Below is my index.ios.js and ProfileView.js, I want to navigate to LoginView from within ProfileView immediately if this.state.toContinue is false. I tried to push the view to this.props.navigator but it didn't work :(
// index.ios.js
"use strict";
var React = require("react-native");
var {
AppRegistry,
StyleSheet,
NavigatorIOS,
} = React;
var ProfileView = require('./ProfileView');
var project = React.createClass({
render: function() {
return (
<NavigatorIOS
style={styles.navigationContainer}
initialRoute={{
title: "Your Profile",
component: ProfileView
}}
/>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}
});
AppRegistry.registerComponent("project", () => project);
// ProfileView.js
"use strict";
var React = require('react-native');
var LoginView = require("./LoginView");
var {
Component,
StyleSheet,
View,
} = React;
class ProfileView extends Component {
constructor (props) {
super(props);
this.state = {
toContinue: this.isSignedIn()
};
}
isSignedIn () {
return false;
}
render () {
if (!this.state.toContinue) {
// jump to LoginView
}
return (
<View style={styles.container}>
<Text>
Welcome
</Text>
</View>
);
}
};
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}
});
module.exports = ProfileView;
Any help is appreciated!
I'm pretty sure the reason it isn't working is that your "this" reference is being changed from where you want it to be by the if statement you have before it in the render function.
Check out what I have here. It is set up and working.
Note that there are known issues regarding the title in NavigatorIOS not functioning correctly when using .replace, discussed here and here.
The working code is also below:
"use strict";
var React = require("react-native");
var {
AppRegistry,
StyleSheet,
NavigatorIOS,
Component,
StyleSheet,
View,
Text
} = React;
var project = React.createClass({
render: function() {
return (
<NavigatorIOS
style={{flex:1}}
initialRoute={{
component: ProfileView
}}
/>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}
});
AppRegistry.registerComponent("project", () => project);
// ProfileView.js
"use strict";
var React = require('react-native');
var LoginView = React.createClass({
render: function() {
return(
<View style={{backgroundColor: 'red', flex:1}}>
<Text style={{marginTop:100}}>Hello from LOGIN VIEW</Text>
</View>
)
}
})
class ProfileView extends Component {
constructor (props) {
super(props);
this.state = {
toContinue: this.isSignedIn()
};
}
isSignedIn () {
return false;
}
changeView() {
this.props.navigator.replace({
component: LoginView,
title: 'LoginView',
})
}
componentDidMount() {
if (!this.state.toContinue) {
this.changeView()
}
}
render () {
return (
<View style={styles.container}>
<Text>
Welcome
</Text>
</View>
);
}
};
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}
});
module.exports = ProfileView;

Can't render based on this.state in React Native

Any idea why {this.state.showTabBar === true ? this._renderTabBar : null} fails in SampleApp component? Works fine if render just <TabBarExample />.
My goal is to use this.state.showTabBar to decide when to show TabBarIOS.
Here's a React Native Playground link:
https://rnplay.org/apps/5pQC9A
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
TabBarIOS,
TouchableHighlight,
} = React;
var SampleApp = React.createClass({
getInitialState: function() {
return {
showTabBar: true // I will eventually use this to decide
// if TabBarIOS will be visible.
};
},
_renderTabBar: function() {
return (
<TabBarExample />
);
},
render: function() {
return (
// This line fails.
{this.state.showTabBar === true ? this._renderTabBar : null}
// <TabBarExample /> // This will work if uncomment.
);
}
});
var TabBarExample = React.createClass({
statics: {
title: '<TabBarIOS>',
description: 'Tab-based navigation.',
},
displayName: 'TabBarExample',
getInitialState: function() {
return {
selectedTab: 'blueTab',
notifCount: 0,
presses: 0,
};
},
_renderContent: function(color: string, pageText: string, num?: number) {
return (
<View style={[styles.tabContent, {backgroundColor: color}]}>
<Text style={styles.tabText}>{pageText}</Text>
<Text style={styles.tabText}>{num} re-renders of the {pageText}</Text>
</View>
);
},
render: function() {
return (
<TabBarIOS
tintColor="white"
barTintColor="darkslateblue"
translucent={true}>
<TabBarIOS.Item
title="Blue Tab"
systemIcon="search"
selected={this.state.selectedTab === 'blueTab'}
onPress={() => {
this.setState({
selectedTab: 'blueTab',
});
}}>
<MyViewOne />
</TabBarIOS.Item>
<TabBarIOS.Item
title="Red Tab"
systemIcon="history"
badge={this.state.notifCount > 0 ? this.state.notifCount : undefined}
selected={this.state.selectedTab === 'redTab'}
onPress={() => {
this.setState({
selectedTab: 'redTab',
notifCount: this.state.notifCount + 1,
});
}}>
{this._renderContent('#783E33', 'Red Tab', this.state.notifCount)}
</TabBarIOS.Item>
<TabBarIOS.Item
systemIcon="contacts"
title="More Green"
selected={this.state.selectedTab === 'greenTab'}
onPress={() => {
this.setState({
selectedTab: 'greenTab',
presses: this.state.presses + 1
});
}}>
{this._renderContent('#21551C', 'Green Tab', this.state.presses)}
</TabBarIOS.Item>
</TabBarIOS>
);
}
});
var MyViewOne = React.createClass({
render: function() {
return (
<View style={[styles.tabContent, {backgroundColor: 'orange'}]}>
<Text style={styles.tabText}>I like Iron Maiden</Text>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
tabContent: {
flex: 1,
alignItems: 'center',
},
tabText: {
color: 'white',
margin: 50,
},
button: {
backgroundColor: 'green',
margin: 10,
}
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);
Like Gortem said, you are not calling the function. React will not do it for you.
Also, instead of a ternary, your could do:
{this.state.showTabBar && this._renderTabBar()}
Or directly:
{this.state.showTabBar && (<TabBarExample />)}
I think you should make showTabBar one of your state:
getInitialState: function(){
return{
showTabBar: {false}
};
}
and use
this.setState({showTabBar:{true}});
to update
You should have your logic outside of the return statement like this:
render: function() {
if (this.state.showTabBar) {
return (this._renderTabBar());
} else {
return (<View />);
}
}
It's also good to note that you will always need to return a component, even if it is a blank View.
Here is the working example: https://rnplay.org/apps/-TjJ7w

react-native propagate changes in props through ListView and Navigator

I have the following situation. I have a parent component that contains a list of items, any of which can be drilled down into and viewed in a child component. From the child component, you should be able to change a value in the item you are looking at.
In the React web world, this would be easy to solve with the parent storing the list as state, and passing the item and a callback for changes as props to the child.
With React Native, it seems like that possibility is lost, since causing a change from the child component does not trigger a re-render until navigating away.
I've recorded a video of what this looks like. https://gfycat.com/GreenAgitatedChanticleer
Code is below.
index.ios.js
var React = require('react-native');
var {
AppRegistry,
Navigator
} = React;
var List = require('./list');
var listviewtest = React.createClass({
render: function() {
return (
<Navigator
initialRoute={{ component: List }}
renderScene={(route, navigator) => {
return <route.component navigator={navigator} {...route.passProps} />;
}} />
);
}
});
AppRegistry.registerComponent('listviewtest', () => listviewtest);
list.js
var React = require('react-native');
var _ = require('lodash');
var {
View,
Text,
TouchableHighlight,
ListView
} = React;
var Detail = require('./detail');
var List = React.createClass({
getInitialState() {
var LANGUAGES = [
{ id: 1, name: 'JavaScript' },
{ id: 2, name: 'Obj-C' },
{ id: 3, name: 'C#' },
{ id: 4, name: 'Swift' },
{ id: 5, name: 'Haskell' }
];
var ds = new ListView.DataSource({ rowHasChanged: (a, b) => a !== b })
return {
languages: LANGUAGES,
ds: ds.cloneWithRows(LANGUAGES)
};
},
goToLanguage(language) {
this.props.navigator.push({
component: Detail,
passProps: {
language: language,
changeName: this.changeName
}
});
},
changeName(id, newName) {
var clone = _.cloneDeep(this.state.languages);
var index = _.findIndex(clone, l => l.id === id);
clone[index].name = newName;
this.setState({
languages: clone,
ds: this.state.ds.cloneWithRows(clone)
});
},
renderRow(language) {
return (
<TouchableHighlight onPress={this.goToLanguage.bind(this, language)}>
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', paddingTop: 5, paddingBottom: 5, backgroundColor: '#fff', marginBottom: 1 }}>
<Text style={{ marginLeft: 5, marginRight: 5 }}>{language.name}</Text>
</View>
</TouchableHighlight>
);
},
render() {
return (
<View style={{ flex: 1, backgroundColor: '#ddd' }}>
<Text style={{ marginTop: 60, marginLeft: 5, marginRight: 5, marginBottom: 10 }}>Select a language</Text>
<ListView
dataSource={this.state.ds}
renderRow={this.renderRow} />
</View>
);
}
});
module.exports = List;
detail.js
var React = require('react-native');
var {
View,
Text,
TouchableHighlight
} = React;
var Detail = React.createClass({
changeName() {
this.props.changeName(this.props.language.id, 'Language #' + Math.round(Math.random() * 1000).toString());
},
goBack() {
this.props.navigator.pop();
},
render() {
return (
<View style={{ flex: 1, backgroundColor: '#ddd', alignItems: 'center', justifyContent: 'center' }}>
<Text>{this.props.language.name}</Text>
<TouchableHighlight onPress={this.changeName}>
<Text>Click to change name</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.goBack}>
<Text>Click to go back</Text>
</TouchableHighlight>
</View>
);
}
});
module.exports = Detail;
Turns out this behavior is intentional, at least for now. There's a discussion thread here: https://github.com/facebook/react-native/issues/795
For anyone looking for a workaround, I'm using RCTDeviceEventEmitter to pass data across Navigator. Updated code below
list.js
var React = require('react-native');
var _ = require('lodash');
var {
View,
Text,
TouchableHighlight,
ListView
} = React;
var Detail = require('./detail');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var List = React.createClass({
getInitialState() {
var LANGUAGES = [
{ id: 1, name: 'JavaScript' },
{ id: 2, name: 'Obj-C' },
{ id: 3, name: 'C#' },
{ id: 4, name: 'Swift' },
{ id: 5, name: 'Haskell' }
];
var ds = new ListView.DataSource({ rowHasChanged: (a, b) => a !== b })
return {
languages: LANGUAGES,
ds: ds.cloneWithRows(LANGUAGES)
};
},
goToLanguage(language) {
this.props.navigator.push({
component: Detail,
passProps: {
initialLanguage: language,
changeName: this.changeName
}
});
},
changeName(id, newName) {
var clone = _.cloneDeep(this.state.languages);
var index = _.findIndex(clone, l => l.id === id);
clone[index].name = newName;
RCTDeviceEventEmitter.emit('languageNameChanged', clone[index]);
this.setState({
languages: clone,
ds: this.state.ds.cloneWithRows(clone)
});
},
renderRow(language) {
return (
<TouchableHighlight onPress={this.goToLanguage.bind(this, language)}>
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', paddingTop: 5, paddingBottom: 5, backgroundColor: '#fff', marginBottom: 1 }}>
<Text style={{ marginLeft: 5, marginRight: 5 }}>{language.name}</Text>
</View>
</TouchableHighlight>
);
},
render() {
return (
<View style={{ flex: 1, backgroundColor: '#ddd' }}>
<Text style={{ marginTop: 60, marginLeft: 5, marginRight: 5, marginBottom: 10 }}>Select a language</Text>
<ListView
dataSource={this.state.ds}
renderRow={this.renderRow} />
</View>
);
}
});
module.exports = List;
detail.js
var React = require('react-native');
var {
View,
Text,
TouchableHighlight
} = React;
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var Detail = React.createClass({
getInitialState() {
return {
language: this.props.initialLanguage,
subscribers: []
};
},
componentDidMount() {
var subscriber = RCTDeviceEventEmitter.addListener('languageNameChanged', language => {
this.setState({ language });
});
this.setState({
subscribers: this.state.subscribers.concat([subscriber])
});
},
componentWillUnmount() {
this.state.subscribers.forEach(sub => {
console.log('removing');
sub.remove();
});
},
changeName() {
this.props.changeName(this.state.language.id, 'Language #' + Math.round(Math.random() * 1000).toString());
},
goBack() {
this.props.navigator.pop();
},
render() {
return (
<View style={{ flex: 1, backgroundColor: '#ddd', alignItems: 'center', justifyContent: 'center' }}>
<Text>{this.state.language.name}</Text>
<TouchableHighlight onPress={this.changeName}>
<Text>Click to change name</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.goBack}>
<Text>Click to go back</Text>
</TouchableHighlight>
</View>
);
}
});
module.exports = Detail;
I wanted to propagate prop change to the rest of route stack as well. And I don't find any way to render renderScene() from the first route.. So I use navigator.replace() instead of updating props. I'm looking for the better way to deal with this because I believe there are a lot of use-case to deal with the route[0] that has info and need to propagate the change to the rest of route stack, like what we do on React props between parent and its children.
# this is on parent component and the change is pushed to props(I'm using Redux)
componentWillReceiveProps(nextProps){
this.props.hubs.map((currentHub) => {
nextProps.hubs.map((hub) => {
if(currentHub.updatedAt !== hub.updatedAt){
this.props.navigator.getCurrentRoutes().map((r, index) => {
if(r.getHubId && ( r.getHubId() === hub.objectId ) ){
let route = Router.getHubRoute(hub);
this.props.navigator.replaceAtIndex(route, index);
}
});
}
})
})

Resources