Native-Base not loading elements - react-native

I am using native-base version 2.0.2, react-native version 0.40.0.
I am following a tutorial to make a GithHub Repo Search using native-base & integrate it with my functionalities to make something different, but all of the components are not properly loaded.
The Header & Footer example from the docs worked fine, but when I add things like searchbar rounded property or the icon classes, it does not get reflected.
When I add the button component I get the following error.
The Code in question is
var constants = require("../constants")
var React = require('react');
var ReactNative = require('react-native');
var t = require('tcomb-form-native');
var authenticate = require("../services/authenticate")
import { Container, Header, Title, Content, Footer, FooterTab, Button, Left, Right, Body,Picker,InputGroup,Icon,Input,Item } from 'native-base';
var {
AppRegistry,
AsyncStorage,
StyleSheet,
Text,
View,
TouchableHighlight,
Alert,
ListView,
Image,
} = ReactNative;
var Form = t.form.Form;
var getFeatured = require("../services/get_featured");
var getCategory = require("../services/get_categories");
var search = require("../services/search");
var Query;
const options = {
fields: {
category: {
order: 'asc',
nullOption: {value: '', text: 'Anything'}
}
}
}
class SplashPage extends React.Component{
constructor() {
super();
this.set_initial_state()
//this.set_categories();
//this.get_featured();
}
set_initial_state(){
this.state ={
hasResult: false,
hasCategory:false,
noResult: false,
isLoading: true,
isLoadingCat:true,
searchResult:false,
categories : [],
searchText:"",
searchCat:"",
filterCat:"",
articles:[],
}
}
set_categories() {
var par = this;
getCategory().then(function(catData){
par.setState({
isLoadingCat:false,
hasCategory:true,
categories:catData,
});
console.error("till here");
});
}
get_categories(){
const cats = this.state.categories;
const CatItems = cats.map((cat,i)=>{
return (
<Picker.item key={i} label={cat} value={cat} />
);
});
return CatItems;
}
openRecipe(data){
this.props.navigator.push({
id: 'RecipePage',
name: 'Recipe',
recipe_id:data.id,
});
}
get_featured(){
var par = this;
getFeatured().then(function(articles){
par.setState(
{
articles:articles,
hasResult: true,
isLoading:false,
searchResult:false,
}
)
}).catch(function(error) {
console.error(error);
});
}
perform_search(){
var value = this.state.searchText;
var par = this;
if(value){
par.setState(
{
hasResult: false,
isLoading:true,
}
)
var category = value.category;
var ingredient = value.ingredient.toString().split(',').join(' ');
search(ingredient,category).then((articles) => {
par.setState(
{
articles:articles,
hasResult: true,
isLoading:false,
searchResult:true
}
)
}).catch(function(error) {
console.error(error);
});
}
}
render() {
return (
<Header searchBar rounded>
<InputGroup>
<Icon name="ios-search" />
<Input placeholder="Search" value={this.state.searchText} onChangeText={(text) => this.setState({searchText:text})} onSubmitEditing={()=>this.search()}/>
<Picker
iosHeader="Select one"
mode="dropdown"
selectedValue={this.state.searchCat}
onValueChange={(cat) => this.setState({searchCat:cat})}>
<Item label="Cats" value="key0" />
<Item label="Cats2" value="key02" />
</Picker>
</InputGroup>
<Button transparent onPress={()=>this.search()}>Go</Button>
</Header>
);
}
}
module.exports = SplashPage;
I checked the dependencies and everything is installed.

I think you should wrap your code in
<Container>
<Content>
// your code
<Button>
<Text>Click Me! </Text>
</Button>
</Content>
</Container>

there's something wrong i think in your Button on onPress.
your code is onPress={()=>this.search()}
but i don't see search() method, i just find perform_search() method
if your problem came after you add <Button> tag, you can change this one :
<Button transparent onPress={()=>this.search()}>Go</Button>
to this one :
<Button transparent onPress={()=>this.perform_search()}><Text>Go</Text></Button>
and also this one : onSubmitEditing={()=>this.search()}
to this one : onSubmitEditing={()=>this.perform_search()}
and don't forget to import Text in native-base, hope can solve your problem :)

Related

Sending push notifications in Expo React Native app to multiple devices at once?

I'm still a newbie to React Native, but I am trying to integrate push notifications to my iOS & Android devices. Most tutorials I have seen with Expo use their website to push a notification using a specific token, but i do not want to do that. I want to send one notification to multiple devices at once (regardless of the OS on the device, aka iOS or Android). I think my best bet is doing it through Firebase, which is what this tutorial does. I also found the GitHub that matches the tutorial, but they use ListView, which is now deprecated. I am getting the error that I cannot use ListView in that Github's code, and when I tried to switch it to a Flatlist, I'm getting an error saying that cloneWithRows is not a function. Can someone help me with that portion of the code? Or if you have alternative resources about how to push a notification to multiple devices let me know please. Edit: I'll post the code below for convenience from the GitHub. All credits go to him. TLDR: Code doesn't work because ListView has been deprecated, and if I change it to FlatList, the cloneWithRows doesn't work. Not sure how to restructure it with a Flatlist, please help if you can.
import React from 'react';
import { StyleSheet, Text, View, StatusBar} from 'react-native';
import { Container, Content, Header, Form, Input, Item, Button, Label, Icon, List } from 'native-base'
import firebase from 'firebase';
import { Permissions, Notifications } from 'expo';
import { FlatList } from 'react-native';
import { ListView } from 'react-native';
var data = []
export default class App extends React.Component {
static navigationOptions = {
header: null
}
constructor(props) {
super(props);
this.ds = new ListView({ rowHasChanged: (r1, r2) => r1 !== r2 })
this.state = {
listViewData: data,
newContact: "",
currentUser: ""
}
}
componentDidMount() {
var currentUser
var that = this
listener = firebase.auth().onAuthStateChanged(function (user) {
if (user != null) {
currentUser = user
that.registerForPushNotificationsAsync(currentUser)
}
listener();
});
firebase.database().ref('/contacts').on('child_added', function (data) {
var newData = [...that.state.listViewData]
newData.push(data)
that.setState({ listViewData: newData })
})
}
loadSubscribers = () => {
var messages = []
//return the main promise
return firebase.database().ref('/subscribers').once('value').then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var childKey = childSnapshot.key;
messages.push({
"to": childKey,
"sound": "default",
"body": "New Note Added"
});
});
//firebase.database then() respved a single promise that resolves
//once all the messages have been resolved
return Promise.all(messages)
}).catch(error => {
console.log(error)
})
}
registerForPushNotificationsAsync = async (currentUser) => {
const { existingStatus } = await Permissions.getAsync(Permissions.NOTIFICATIONS);
let finalStatus = existingStatus;
// only ask if permissions have not already been determined, because
// iOS won't necessarily prompt the user a second time.
if (existingStatus !== 'granted') {
// Android remote notification permissions are granted during the app
// install, so this will only ask on iOS
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
// Stop here if the user did not grant permissions
if (finalStatus !== 'granted') {
return;
}
// Get the token that uniquely identifies this device
let token = await Notifications.getExpoPushTokenAsync();
// POST the token to our backend so we can use it to send pushes from there
var updates = {}
updates['/expoToken'] = token
await firebase.database().ref('/users/' + currentUser.uid).update(updates)
//call the push notification
}
addRow(data) {
var key = firebase.database().ref('/contacts').push().key
firebase.database().ref('/contacts').child(key).set({ name: data })
}
async deleteRow(secId, rowId, rowMap, data) {
await firebase.database().ref('contacts/' + data.key).set(null)
rowMap[`${secId}${rowId}`].props.closeRow();
var newData = [...this.state.listViewData];
newData.splice(rowId, 1)
this.setState({ listViewData: newData });
}
render() {
return (
<Container style={styles.container} >
<Header style={{ marginTop: StatusBar.currentHeight }}>
<Content>
<Item>
<Input
onChangeText={(newContact) => this.setState({ newContact })}
placeholder="Add Note"
/>
<Button onPress={() => this.addRow(this.state.newContact)}>
<Icon name="add" />
</Button>
</Item>
</Content>
</Header>
<Content>
<List
enableEmptySections
dataSource={this.ds.cloneWithRows(this.state.listViewData)}
renderRow={data =>
<ListItem>
<Text> {data.val().name}</Text>
</ListItem>
}
renderLeftHiddenRow={data =>
<Button full onPress={() => this.addRow(data)} >
<Icon name="information-circle" />
</Button>
}
renderRightHiddenRow={(data, secId, rowId, rowMap) =>
<Button full danger onPress={() => this.deleteRow(secId, rowId, rowMap, data)}>
<Icon name="trash" />
</Button>
}
leftOpenValue={-75}
rightOpenValue={-75}
/>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});

Clearing Input in React Native

I'm new to react native.
I've created a react native app and my first screen is a login screen. I'm using onChangeText to update state vars with username and password and this works great initially.
However on "logout" when I pop back to the login screen. The inputs still have my username and password in. However the state vars are now back to null.
I've tried setting value to {this.state.username} for the input but this just causes a depth error on state after 2 input presses so doesn't work.
Am I missing something?
import React, { Component } from 'react';
import { View, Text, StyleSheet, Image, Alert, AsyncStorage, Linking } from 'react-native';
import { Input, Left, Spinner, Container, Item, Form, Header, Content, Label, Button } from 'native-base'
export default class Login extends Component {
state = { username: "", password: "", isLoaded: true }
static navigationOptions = {
header: null
}
constructor(props) {
super()
this.state.isLoaded = false
AsyncStorage.getItem("loggedIn").then(res => {
if (res === "true") {
this.props.navigation.navigate('List')
}
else {
this.setState({isLoaded: true})
}
})
}
checkLogin() {
if ((!this.state.username) || (!this.state.password)) {
Alert.alert('Error', 'Username/Password combination unknown', [{
text: 'Okay'
}])
return
}
....... snip ......
if (response === false) {
Alert.alert('Error', 'Username/Password combination unknown', [{
text: 'Okay'
}])
}
else {
AsyncStorage.setItem('user', JSON.stringify(response));
AsyncStorage.setItem('loggedIn', "true");
this.setState({username: null, password: null})
this.props.navigation.navigate('List')
}
}
}
render()
{
if (this.state.isLoaded == false) {
return (
<Container>
<Spinner />
</Container>
)
}
return (
<Container>
<Content>
<Image source={require('../../assets/logo.jpg')}/>
<Form>
<Item floatingLabel>
<Label>Username</Label>
<Input
autoCapitalize='none'
clearButtonMode='always'
onChangeText={text => this.setState({username:text})} />
</Item>
<Item floatingLabel>
<Label>Password</Label>
<Input
secureTextEntry={true}
clearButtonMode='always'
onChangeText={text => this.setState({password: text})} />
</Item>
<Button primary onPress={_ => this.checkLogin()}>
<Text style={styles.loginButtonText}>Login</Text>
</Button>
</Form>
</Content>
</Container>
);
}
}
You can use direct manipulation method.
Try passing ref to Input like ref={ (c) => this._input = c } and then calling the setNativeProps function this._input.setNativeProps({text:''})
I am also using react navigation and face similar issue.
I fixed as below :
import { NavigationEvents } from "react-navigation";
class ... {
onStartScreenFocus = ()>={
this.setState({
username: "", password: ""
})
}
render(){
return(
<View>
<NavigationEvents
onWillFocus={() => this.onStartScreenFocus()}
onDidBlur={() => this.onDidScreenBlur()} />
<View>
)
}
}

React Native State is Undefined Vasern

I am actually starting with Mobile Development and React Native and I thought an interesting Database called Vasern But now I am trying to load things from my database with the componentDidMount() method but i actually just get this Error everytime.
I am sure its just a trivial Error but i just cant find it...
Thanks in Advance
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
Button,
SectionList
} from 'react-native';
import Vasern from 'vasern';
import styles from './styles';
const TestSchema = {
name: "Tests",
props: {
name: "string"
}
}
const VasernDB = new Vasern({
schemas: [TestSchema],
version: 1
})
const { Tests } = VasernDB;
var testList = Tests.data();
class Main extends Component {
state = {
tests: [],
};
constructor(props){
super(props);
this._onPressButton = this._onPressButton.bind(this);
this._onPressPush = this._onPressPush.bind(this);
this._onPressUpdate = this._onPressUpdate.bind(this);
this._onPressDeleteAll = this._onPressDeleteAll.bind(this);
}
componentDidMount() {
Tests.onLoaded(() => this._onPressButton());
Tests.onChange(() => this._onPressButton());
}
_onPressButton = () => {
let tests = Tests.data();
console.log(tests);
//if( tests !== undefined){
this.setState({tests}); // here is the error
//alert(tests);
//}
}
_onPressPush = () => {
Tests.insert({
name: "test"
});
console.log(this.state.tests + "state tests"); //here the console only shows the text
}
_onPressUpdate = () => {
var item1 = Tests.get();
Tests.update(item1.id, {name: "test2"});
}
_onPressDelete = () => {
}
_onPressDeleteAll = () => {
let tests = Tests.data();
tests.forEach((item, i) => {
Tests.remove(item.id)
});
}
_renderHeaderItem({ section }) {
return this._renderItem({ item: section});
}
_renderItem({ item }){
return <View><Text>{item.name}</Text></View>
}
render() {
//const { tests = [] } = this.props;
return (
<View style={styles.container}>
<View>
<TextInput> Placeholder </TextInput>
<Button title="Press me for Show" onPress={this._onPressButton}/>
<Button title="Press me for Push" onPress={this._onPressPush}/>
<Button title="Press me for Update" onPress={this._onPressUpdate}/>
<Button title="Press me for Delete" onPress={this._onPressDelete}/>
<Button title="Press me for Delete All" onPress={this._onPressDeleteAll}/>
</View>
<View style={styles.Input}>
<SectionList
style={styles.list}
sections={this.state.tests}
keyExtractor={item => item.id}
renderSectionHeader={this._renderHeaderItem}
contentInset={{ bottom: 30 }}
ListEmptyComponent={<Text style={styles.note}>List Empty</Text>}
/>
</View>
</View>
);
}
}
export default Main;
Since Tests.data() will return an array (as list of records).
In React Native, you might use FlatList to display an array of records.
import { ..., FlatList } from 'react-native';
...
// replace with SectionList
<FlatList
renderItem={this._renderItem} // item view
data={this.state.tests} // data array
style={styles.list}
keyExtractor={item => item.id}
contentInset={{ bottom: 30 }}
ListEmptyComponent={<Text style={styles.note}>List Empty</Text>}
/>
In case you want to use SectionList, you will need to reform data into sections. Something like:
var sections = [
{title: 'Title1', data: ['item1', 'item2']},
{title: 'Title2', data: ['item3', 'item4']},
{title: 'Title3', data: ['item5', 'item6']},
]
Besides, React Native is in a really good state. I think you will like it.

Error while updating property 'd' of a view managed by: RNSVGPath

I am struggling for last few days with the below error in react native.
My intention:
Dynamically fetch chart data and plot multiple charts on my page.
Whenever I have a succesful fetch the sData[] gets filled. However my chart keeps thrwoing an error:
Error while updating property 'd' of a view managed by: RNSVGPath
null
Attempt to invoke interface method 'int java.Charsequence.length()' on a null object reference
If the fetch fails and my sData is set to default array [5,4,3,2,1] as below in the code, the chart is able to render.
What am i missing/messing? Please help.
import React, { Component } from 'react';
import {AsyncStorage} from 'react-native';
import { LineChart, Grid } from 'react-native-svg-charts';
import { Container, Header, Content, List, ListItem, Text, Left, Right, Body , Button, Title} from 'native-base';
const data = [1,2,3,4,5,6,7];
export default class SomeDetails extends Component {
constructor(props)
{
super(props);
this.state = { 'user': '',
'email': '',
'privLevel': '',
'phNum': '',
UserApiUrl: '<SOMEAPI>',
sData: [],
someData: ''
}
}
componentDidMount() {
this._loadInitialState().done();
}
_loadInitialState = async () => {
var uPhVal = await AsyncStorage.getItem('uPh');
var uEmailVal = await AsyncStorage.getItem('uEmail');
var uPrivVal = await AsyncStorage.getItem('uPlevel');
var uName = await AsyncStorage.getItem('username');
if(uName !== null)
{
this.setState({'user': uName});
this.setState({'phNum': uPhVal});
this.setState({'email': uEmailVal});
this.setState({'privLevel':uPrivVal})
}
var postString = "SOME STRING FOR MY API"
console.log(postString);
response = await fetch(this.state.UserApiUrl, {
method: 'POST',
body: postString
})
res = await response.json();
console.log(res.success);
if (res.success == "true") {
this.setState({ someData: res.someLatestVal });
var dataItems = this.state.someData.split(';');
for(let j=0;j<dataItems.length; j++)
{
var dataI = dataItems[j].split(':');
this.setState({sData: this.state.sData.concat([dataI[0]]) } );
}
}
else {
// console.log("Req: Unable to fetch");
this.setState({sData: [1,2,3,4,5]});
this.setState({loading: true});
}
console.log(this.state.sData);
}
render() {
const { navigation } = this.props;
const someName = navigation.getParam('someName', 'no-name');
return (
<Container>
<Content>
<List>
<ListItem>
<Text>Sensorname: { someName } </Text>
</ListItem>
<LineChart
style={{ height: 70, width: 120 }}
data={ this.state.sData }
svg={{ stroke: 'rgb(134, 65, 244)' }}
contentInset={{ top: 20, bottom: 20 }}
>
<Grid/>
</LineChart>
</List>
</Content>
</Container>
);
}
}
We fixed this by ensuring VictoryLine always gets at least 2 data points. If passed only one data point it may crash.
Here's the working code with a simple check for whether a data set has at least two items:
{dataSetsWithGaps.map(coordList =>
coordList.length < 2 ? null : (
<VictoryLine
key={`line_${coordList[0].x.toString()}`}
interpolation={interpolationMethod}
data={coordList}
/>
),
)}
remove - yarn remove react-native-svg
add - yarn add react-native-svg#9.13
it worked for me

get active tab from Closable TabPanel in extReact sencha component

I'm making Closable TabPanel and at the moment when I click on the certain tab I will switch to the Panel of that's tab. What Panel's tab I click, that Panel opens. That's great.
but now I want to have a carousel button on the side, to list next, next, next Panel.
Which means I need to know on what panel I am at the moment (what panel is active now)? And How to tell take next panel in the row ( setPanel(activeId+1) ) ?
For now, I'm getting a list of all existing PANELS and I extract all their IDs: [45,46,47,48,49]. I'm getting it form DataBase, but I don't know how to get currently Active panel and how to say go to next!?
Any ideas?
use property: activeItem={2}
for example: <TabPanel activeItem={this.state.componentNumber} border={false} ...> </TabPanel>
App.js
import React, { Component } from 'react';
import { Button } from '#extjs/ext-react';
import ClosableComponent from './ClosableComponent';
class App extends Component {
constructor() {
super();
this.state = {
componentNumber: 2,
};
}
switchFunctionLeft = () => {
if(this.state.componentNumber === 0){
this.setState({ componentNumber: 2 })
}else{
this.setState({ componentNumber: this.state.componentNumber - 1 })
}
}
switchFunctionRight = () => {
if(this.state.componentNumber === 2){
this.setState({ componentNumber: 0 })
}else{
this.setState({ componentNumber: this.state.componentNumber + 1 })
}
}
render() {
return (
<div className="App">
<div >
<ClosableComponent componentNumber={this.state.componentNumber} />
<Button text="switch to left" handler={this.switchFunctionLeft} />
<Button text="switch to right" handler={this.switchFunctionRight}/>
</div>
</div>
);
}
}
export default App;
ClosableComponent.js
import React, {
Component
} from 'react';
import {
TabPanel,
Container,
Toolbar,
Button
} from '#extjs/ext-react';
class ClosableComponent extends Component {
nextKey = 0;
constructor() {
super();
this.state = {
type: "No",
switch: "",
tabs: [
this.nextKey++,
this.nextKey++,
this.nextKey++
]
};
}
onCloseTab = tab => {
const tabs = this.state.tabs.filter(t => t !== tab);
this.setState({
tabs
})
}
addTab = () => {
const key = this.nextKey++;
const tabs = [...this.state.tabs, key];
this.setState({tabs})
this.tabPanel.setActiveItem(tabs.indexOf(2))
return false;
}
render() {
const { tabs } = this.state;
return (
<div>
<Container layout="fit" padding = {10}>
<TabPanel
ref = {tp => this.tabPanel = tp}
_reactorIgnoreOrder
shadow
style={{ backgroundColor: 'white', "height": "200px"}}
activeItem={this.props.componentNumber}
tabBar={{
height: 48,
layout: {
pack: 'left'
},
style: {
paddingRight: '52px'
}
}}
>
{ tabs.map(key => (
<Container
title = {`Tab ${key}`}
tab = {{ flex: 1, maxWidth: 150 }}
key = {key}
layout = "center"
closable
onDestroy = {this.onCloseTab.bind(this, key)}
>
<div style = {{ whiteSpace: 'nowrap' }}>Tab {key} Content</div>
</Container>
))}
</TabPanel>
<Button
top={18}
right={20}
iconCls="x-fa fa-plus"
handler={this.addTab}
ui="alt round"
tooltip="New Tab"
/>
</Container>
</div>
);
}
}
export default ClosableComponent;