I want to use relamDb in my react native expo project. I run the following command to install realm in my project-
npm install --save realm
it doesn't show any error while installing. After installing, in my project I have created two classes - App.js and TodoListComponent.js
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import TodoListComponent from './components/TodoListComponent';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<TodoListComponent/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
TodoListComponent.js
import React, { Component } from 'react';
import { View, FlatList, Text, TouchableOpacity, StyleSheet, Alert } from 'react-native';
import { updateTodoList, deleteTodoList, queryAllTodoLists } from '../databases/allSchemas';
import realm from '../databases/allSchemas';
import Swipeout from 'react-native-swipeout';
import HeaderComponent from './HeaderComponent';
import PopupDialogComponent from './PopupDialogComponent';
let FlatListItem = props => {
const { itemIndex, id, name, creationDate, popupDialogComponent, onPressItem } = props;
showEditModal = () => {
popupDialogComponent.showDialogComponentForUpdate({
id, name
});
}
showDeleteConfirmation = () => {
Alert.alert(
'Delete',
'Delete a todoList',
[
{
text: 'No', onPress: () => { },//Do nothing
style: 'cancel'
},
{
text: 'Yes', onPress: () => {
deleteTodoList(id).then().catch(error => {
alert(`Failed to delete todoList with id = ${id}, error=${error}`);
});
}
},
],
{ cancelable: true }
);
};
return (
<Swipeout right={[
{
text: 'Edit',
backgroundColor: 'rgb(81,134,237)',
onPress: showEditModal
},
{
text: 'Delete',
backgroundColor: 'rgb(217, 80, 64)',
onPress: showDeleteConfirmation
}
]} autoClose={true}>
<TouchableOpacity onPress={onPressItem}>
<View style={{ backgroundColor: itemIndex % 2 == 0 ? 'powderblue' : 'skyblue' }}>
<Text style={{ fontWeight: 'bold', fontSize: 18, margin: 10 }}>{name}</Text>
<Text style={{ fontSize: 18, margin: 10 }} numberOfLines={2}>{creationDate.toLocaleString()}</Text>
</View>
</TouchableOpacity>
</Swipeout >
);
}
export default class TodoListComponent extends Component {
constructor(props) {
super(props);
this.state = {
todoLists: []
};
this.reloadData();
realm.addListener('change', () => {
this.reloadData();
});
}
reloadData = () => {
queryAllTodoLists().then((todoLists) => {
this.setState({ todoLists });
}).catch((error) => {
this.setState({ todoLists: [] });
});
console.log(`reloadData`);
}
render() {
return (<View style={styles.container}>
<HeaderComponent title={"Todo List"}
hasAddButton={true}
hasDeleteAllButton={true}
showAddTodoList={
() => {
this.refs.popupDialogComponent.showDialogComponentForAdd();
}
}
/>
<FlatList
style={styles.flatList}
data={this.state.todoLists}
renderItem={({ item, index }) => <FlatListItem {...item} itemIndex={index}
popupDialogComponent={this.refs.popupDialogComponent}
onPressItem={() => {
alert(`You pressed item `);
}} />}
keyExtractor={item => item.id}
/>
<PopupDialogComponent ref={"popupDialogComponent"} />
</View>);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-start',
},
flatList: {
flex: 1,
flexDirection: 'column',
}
});
After these coding, when I run the application it shows the following error-
missing Realm constructor. Did you run "react-native link realm" ? Please see https://realm.io/docs/react-native/latest/#missing-realm-constructor for troubleshooting
I have tried to find out problem from the below links-
https://github.com/realm/realm-js/issues/1407
https://github.com/realm/realm-js/issues/1340
But none of these were helpful to me. So, it would be very nice if some one helps me to know how to use realmDb in React native expo project.
Expo does not support realm.
You will have to eject from expo and then start using realm
Please note that Expo does not support Realm, From the docs.
Old Question, but you can now by using their template:
https://www.npmjs.com/package/#realm/expo-template-ts
https://www.mongodb.com/docs/realm/sdk/react-native/quick-start-expo/
Related
I'm learning react native through a book and I was following the guide step by step. As I was coding and seeing the changes in the app I came across this error and I don't know what it means. I reviewed the code and compared with the code of the book and it's the same. I also searched the internet for some answers and couldn't find any. I'd be really glad if someone could tell me what I'm doing wrong here.
Here's the error I'm getting on the app:
The error in the windows terminal:
TypeError: undefined is not an object (evaluating '_this.submitTodo.bind')
This error is located at:
in App (at TodoApp/index.js:9)
in TodoApp (at renderApplication.js:50)
in RCTView (at View.js:32)
in View (at AppContainer.js:92)
in RCTView (at View.js:32)
in View (at AppContainer.js:119)
in AppContainer (at renderApplication.js:43)
in TodoApp(RootComponent) (at renderApplication.js:60)
Here's the App.js code:
import React, { Component } from 'react'
import { View, ScrollView, StyleSheet } from 'react-native'
import Heading from './Heading'
import Input from './Input'
import Button from './Button'
let todoIndex = 0
class App extends Component {
constructor() {
super()
this.state = {
inputValue: '',
todos: [],
type: 'All'
}
this.submitTodo = this.submitTodo.bind(this)
}
inputChange(inputValue) {
console.log(' Input Value: ' , inputValue)
this.setState({ inputValue })
}
sumbitTodo () {
if (this.state.inputValue.match(/^\s*$/)) {
return
}
const todo = {
title: this.state.inputValue,
todoIndex,
complete: false
}
todoIndex++
const todos = [...this.state.todos, todo]
this.setState({ todos, inputValue: '' }, () => {
console.log('State: ', this.state)
})
}
render () {
const { inputValue } = this.state
return (
<View style={styles.container}>
<ScrollView keyboardShouldPersistTaps='always' style={styles.content}>
<Heading />
<Input
inputValue={inputValue}
inputChange={ (text) => this.inputChange(text) } />
<Button submitTodo={this.submitTodo} />
</ScrollView>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5'
},
content: {
flex: 1,
paddingTop: 60
}
})
export default App
Here's the Button.js code which might help:
import React from 'react'
import { View, Text, StyleSheet, TouchableHighlight } from 'react-native'
const Button = ({ submitTodo }) => (
<View style={styles.buttonContainer}>
<TouchableHighlight
underlayColor='#efefef'
style={styles.button}
onPress={submitTodo}>
<Text style={styles.submit}>
Submit
</Text>
</TouchableHighlight>
</View>
)
const styles = StyleSheet.create({
buttonContainer: {
alignItems: 'flex-end'
},
button: {
height: 50,
paddingLeft: 20,
paddingRight: 20,
backgroundColor: '#ffffff',
width: 200,
marginRight: 20,
marginTop: 15,
borderWidth: 1,
borderColor: 'rgba(0,0,0,.1)',
justifyContent: 'center',
alignItems: 'center'
},
submit: {
color: '#666666',
fontWeight: '600'
}
})
export default Button
Here's the Input.js code which might help as well.
import React from 'react'
import { View, TextInput, StyleSheet } from 'react-native'
const Input = ({ inputValue, inputChange }) => (
<View style={styles.inputContainer}>
<TextInput
value={inputValue}
style={styles.input}
placeholder='What needs to be done?'
placeholderTextColor='#CACACA'
selectionColor='#666666'
onChangeText={inputChange} />
</View>
)
const styles = StyleSheet.create({
inputContainer: {
marginLeft: 20,
marginRight: 20,
shadowOpacity: 0.2,
shadowRadius: 3,
shadowColor: '#000000',
shadowOffset: { width: 2, height: 2 }
},
input: {
height: 60,
backgroundColor: '#ffffff',
paddingLeft: 10,
paddingRight: 10,
}
})
export default Input
I have an issue in my project. I want to show elements after I get them from the JSON. When I am trying to observe content of JSON I see it, but when I am trying to show it in my component it doesn't appear. Also debugger don't show any errors or problrms and app compiles sucessfully. I am really stuck, so I really need your help guys
App.js code:
import React, { Component } from 'react'
import { View, ScrollView, StyleSheet } from 'react-native'
import { Header, ImageCard } from './src/components/uikit'
const url = 'https://s3.eu-central-1.wasabisys.com/ghashtag/RNForKids/00-Init/data.json'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
title: 'STAR GATE',
data: []
};
}
componentDidMount = async () => {
try {
const response = await fetch(url)
const data = await response.json()
this.setState({ data })
}
catch (e) {
console.log(e)
throw e
}
}
render() {
const { title, data } = this.state
const { container } = style
return (
<View>
<Header title={title} />
<ScrollView>
<View style={container}>
{data.map(item => {
<ImageCard data={item} key={item.id} />
})
}
</View>
</ScrollView>
</View>
)
}
}
const style = StyleSheet.create({
container: {
marginTop: 30,
flexDirection: 'row',
flexWrap: 'wrap',
flexShrink: 2,
justifyContent: 'space-around',
marginBottom: 150,
backgroundColor: 'gold',
width: 150
}
})
My problem happens in App.js inside the
And ImageCard code:
import React from 'react'
import { Image, View, Text, StyleSheet } from 'react-native'
import { h, w } from '../../../constants'
const ImageCard = ({data}) => {
const {container, sub, h2, cover} = styles
const {image, name} = data
return (
<View style={container}>
<View style={sub}>
<Image
style={cover}
source={{
uri: image,
}}
/>
</View>
<Text style={h2}>{name.toUpperCase()}</Text>
</View>
)
}
const styles = StyleSheet.create({
container: {
width: w / 2.1,
paddingVertical: 10,
},
sub: {
padding:10,
shadowColor: 'black',
shadowRadius: 8,
shadowOffset: { width: 0, height: 5 },
shadowOpacity: 0.4,
},
h2: {
fontFamily: 'AvenirNext-DemiBold',
fontSize: 16,
alignSelf: 'center',
textAlign: 'center',
width: w / 2.4
},
cover: {
width: w / 2.4,
height: w * 0.63,
borderRadius: 10
}
})
export { ImageCard }
It should be ok, I made it by guide, but something went wrong.
It looks like you're not returning anything from map!
data.map(item => {
<ImageCard data={item} key={item.id} />
})
should become
data.map(item => {
return <ImageCard data={item} key={item.id} />
})
// OR
data.map(item => ( // <-- Note the bracket change
<ImageCard data={item} key={item.id} />
))
I need a function that creates new screens with a webview in it.
The main screen of my expo app contains a button "add new Page" which links to a page with a form to add domain, Username, Password.
if this is done, I want a list of pages in my main screen with all pages. for example if I click on "myWebsite1" with the generated link http://user:password#myWebsite1.com this page should be shown in a webview. same for website2, 3 and so on.
Anyone an idea how to do this?
EDIT: I add some code I have right now. For each Task I create, the Domain, User and Password for the webview file should change and be saved at this specific task. (and also open onclick). I turn in a circle
this is my app.js which expo opens first, it contains a Flatlist:
import React, { Component } from "react";
import { AppRegistry, StyleSheet, Text, View, FlatList, AsyncStorage, Button, TextInput, Keyboard, Platform, TouchableWithoutFeedback } from "react-native";
const isAndroid = Platform.OS == "android";
const viewPadding = 10;
const things = {things}
export default class NodeList extends Component {
state = {
tasks: [ ],
text: ""
};
changeTextHandler = text => {
this.setState({ text: text });
};
addTask = () => {
let notEmpty = this.state.text.trim().length > 0;
if (notEmpty) {
this.setState(
prevState => {
let { tasks, text } = prevState;
return {
tasks: tasks.concat({ key: tasks.length, text: text }),
text: ""
};
},
() => Tasks.save(this.state.tasks)
);
}
};
deleteTask = i => {
this.setState(
prevState => {
let tasks = prevState.tasks.slice();
tasks.splice(i, 1);
return { tasks: tasks };
},
() => Tasks.save(this.state.tasks)
);
};
componentDidMount() {
Keyboard.addListener(
isAndroid ? "keyboardDidShow" : "keyboardWillShow",
e => this.setState({ viewMargin: e.endCoordinates.height + viewPadding })
);
Keyboard.addListener(
isAndroid ? "keyboardDidHide" : "keyboardWillHide",
() => this.setState({ viewMargin: viewPadding })
);
Tasks.all(tasks => this.setState({ tasks: tasks || [] }));
}
render() {
return (
<View
style={[styles.container, { paddingBottom: this.state.viewMargin }]}
>
<Text style={styles.appTitle}>Nodes</Text>
<FlatList
style={styles.list}
data={this.state.tasks}
renderItem={({ item, index }) =>
<View>
<View style={styles.listItemCont}>
<TouchableWithoutFeedback onPress={() => Linking.openURL('')}>
<Text style={styles.listItem}>
{item.text}
</Text>
</TouchableWithoutFeedback>
<Button color= "#00BC8C" title="✖" onPress={() => this.deleteTask(index)} />
</View>
<View style={styles.hr} />
</View>}
/>
<TextInput
style={styles.textInput}
onChangeText={this.changeTextHandler}
onSubmitEditing={this.addTask}
value={this.state.text}
placeholder="+ add Node"
returnKeyType="done"
returnKeyLabel="done"
/>
</View>
);
}
}
let Tasks = {
convertToArrayOfObject(tasks, callback) {
return callback(
tasks ? tasks.split("||").map((task, i) => ({ key: i, text: task })) : []
);
},
convertToStringWithSeparators(tasks) {
return tasks.map(task => task.text).join("||");
},
all(callback) {
return AsyncStorage.getItem("TASKS", (err, tasks) =>
this.convertToArrayOfObject(tasks, callback)
);
},
save(tasks) {
AsyncStorage.setItem("TASKS", this.convertToStringWithSeparators(tasks));
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#252525",
padding: viewPadding,
paddingTop: 24
},
list: {
width: "100%"
},
listItem: {
paddingTop: 4,
paddingBottom: 2,
fontSize: 18,
color:"#ffff"
},
hr: {
height: 1,
backgroundColor: "gray"
},
listItemCont: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingTop: 10,
},
textInput: {
height: 40,
paddingRight: 10,
paddingLeft: 10,
borderColor: "gray",
borderWidth: isAndroid ? 0 : 1,
width: "100%",
color:"#ffff"
},
appTitle: {
alignItems:"center",
justifyContent: "center",
paddingBottom: 45,
marginTop: 50,
fontSize: 25,
color:"#ffff"
}
});
AppRegistry.registerComponent("NodeList", () => NOdeList);
and here is my second screen, which contains the component for the WebView:
import React, { Component, useState } from "react";
import { BackHandler } from 'react-native';
import { WebView } from 'react-native-webview';
var $ = require( "jquery" );
export default class nodeView extends Component {
constructor(props) {
super(props);
this.WEBVIEW_REF = React.createRef();
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
handleBackButton = ()=>{
this.WEBVIEW_REF.current.goBack();
return true;
}
onNavigationStateChange(navState) {
this.setState({
canGoBack: navState.canGoBack
});
}
render(){
return (
<WebView
source={{ uri: `https://${user}:${password}#${domain}` }}
ref={this.WEBVIEW_REF}
style={{ marginTop: 20 }}
onNavigationStateChange={this.onNavigationStateChange.bind(this)}
/>
)
}
}
Create WebView. Create State Which Controls WebView. Add Listener To Button
Problem with stack navigation between the screens.
I am displaying data on my 'SveKategorije' screen.
It's basically categories buttons, when i click on button i just want to show another screen for now, but it is not working for some reason.
When i put onPress={() => this.props.navigation.navigate('screenname')}
it gives me this
error
I am using (react-native - 0.57.7)
Here is router.js code (where i declare my routes)
import React from 'react';
import { View, Text, Button } from "react-native";
import { createBottomTabNavigator, createStackNavigator } from "react-navigation";
import { Icon } from 'react-native-elements';
//TABS
import Categories from '../tabs/categories';
import Home from '../tabs/home';
import Me from '../tabs/me';
//screens for CATEGORIES
import ViceviPoKategoriji from '../components/Ispis/ViceviPoKategoriji';
//CATEGORIES STACK
export const categoriesFeedStack = createStackNavigator({
SveKategorije: {
screen: Categories,
navigationOptions: {
title: 'KATEGORIJE',
},
},
ViceviPoKategoriji: {
screen: ViceviPoKategoriji,
}
});
//TABS
export const Tabs = createBottomTabNavigator({
Categories: {
screen: categoriesFeedStack,
navigationOptions: {
title: 'Kategorije',
label: 'Kategorije',
tabBarIcon: ({ tintColor }) => <Icon name="list" size={35} color={tintColor} />,
}
},
Home: {
screen: Home,
navigationOptions: {
title: 'Pocetna',
label: 'Kategorije',
tabBarIcon: ({ tintColor }) => <Icon name="home" size={35} color={tintColor} />,
}
},
Me: {
screen: Me,
navigationOptions: {
title: 'Profil',
label: 'Kategorije',
tabBarIcon: ({ tintColor }) => <Icon name="account-circle" size={35} color={tintColor} />,
}
},
},
{
initialRouteName: "Home",
showIcon: true
},
);
Here is 'SveKategorije' screen
import React from 'react';
import { StyleSheet, Text, View, ActivityIndicator, ScrollView, Button } from 'react-native';
import { createStackNavigator, createAppContainer, StackNavigator, navigate } from 'react-navigation';
export default class SveKategorije extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null
}
}
componentDidMount() {
return fetch('http://centarsmijeha.com/api/allCategories')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
})
})
.catch((error) => {
console.log(error)
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
)
} else {
let data = this.state.dataSource.map((val, key) => {
return (
<View key={key} style={styles.item}>
<Button
onPress={() => this.props.navigation.navigate('ViceviPoKategoriji')}
title={val.categoryName}
/>
</View>
);
});
return (
<ScrollView>
{data}
</ScrollView >
);
}
}
}
//CSS
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
width: '100%'
},
item: {
flex: 1,
alignSelf: 'stretch',
width: '100%',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center'
}
});
and here is 'ViceviPoKategoriji' screen ( the screen that should be displayed on click of any buttons from 'SveKategorije' screen )
import React from 'react';
import { StyleSheet, Text, View, ActivityIndicator, ScrollView } from 'react-native';
export default class ViceviPoKategoriji extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
}
}
componentDidMount() {
return fetch('http://centarsmijeha.com/api/jokesByCategory/16')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
})
})
.catch((error) => {
console.log(error)
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
)
} else {
let data = this.state.dataSource.map((val, key) => {
return <View key={key} style={styles.item}><Text>{val.jokeText}</Text></View>
});
return (
<ScrollView>
{data}
</ScrollView >
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
item: {
flex: 1,
alignSelf: 'stretch',
marginTop: 50,
marginRight: '15%',
marginLeft: '15%',
width: '70%',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
borderBottomWidth: 1,
borderBottomColor: '#eee'
}
});
React-navigation is props based navigation.
I think your component don't have navigation props.
Please check whether your component have navigation props.
do
render() {
console.log(this.props.navigation)
// or debugger
return (
If result of console.log is undefined, then add 'import SveKategorije' to your routing file.
You have to do few more setups for navigating from the component.You can get access to a navigator through a ref and pass it to the NavigationService which we will later use to navigate.
https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
In my case I accidentally used this.props.navigation inside functional component. If any one made a mistake like this, will check u r code once again.
I have a component for listing items, I want to add the function that can go to a different page, and that page has the detail about that item. Currently, this is my code for listing items.
import React, { Component } from 'react';
import { ScrollView } from 'react-native';
import axios from 'axios';
import CarDetail from './CarDetail';
const API_URL = 'http://localhost:3000';
class CarList extends Component {
state = { cars: [] };
componentWillMount() {
console.log('Mount');
axios.get(`${API_URL}/cars`)
.then(response => this.setState({ cars: response.data.cars }));
}
renderCars() {
return this.state.cars.map(car => <CarDetail key={car.id} car={car} />
);
}
render() {
console.log(this.state.cars);
return (
<ScrollView>
{this.renderCars()}
</ScrollView>
);
}
}
export default CarList;
and this is the code for describing items
import React from 'react';
import { Text, View, Image } from 'react-native';
import { Actions } from 'react-native-router-flux';
import Card from '../material/Card';
import CardSection from '../material/CardSection';
const CarDetail = ({ car }) => {
const imageURI = 'https://yt3.ggpht.com/-HwO-2lhD4Co/AAAAAAAAAAI/AAAAAAAAAAA/p9WjzQD2-hU/s900-c-k-no-mo-rj-c0xffffff/photo.jpg';
const { make, model } = car;
function showCarDetail() {
Actions.showCar();
}
return (
<Card>
<CardSection>
<View style={styles.containerStyle}>
<Image
style={styles.imageStyle}
source={{ uri: imageURI }}
/>
</View>
<View style={styles.headContentStyle}>
<Text
style={styles.headerTextStyle}
onPress={showCarDetail()}
>
{make}
</Text>
<Text>{model}</Text>
</View>
</CardSection>
<CardSection>
<Image
style={styles.picStyle}
source={require('./car.jpg')}
/>
</CardSection>
</Card>
);
};
const styles = {
headContentStyle: {
flexDirection: 'column',
justifyContent: 'space-around'
},
headerTextStyle: {
fontSize: 18
},
imageStyle: {
height: 50,
width: 50
},
containerStyle: {
justifyContent: 'center',
alignItems: 'center',
marginLeft: 10,
marginRight: 10
},
picStyle: {
height: 300,
flex: 1,
width: null
}
};
export default CarDetail;
How can I change my code for that? Can anyone give me an example?
You have to use some sort of navigation component. There are many out there, but personally I use the one that is built into React Native. https://facebook.github.io/react-native/docs/navigator.html