How to solve the problem for stackNavigator - javascript

Here In this code I am populating json data on ListView ..and after click item value, passing that particular value on new screen.. .
I have created MainActivity where I am populating JSON value and on SecondActivity sendng selected item value ,
To navigate between class I am using
export default MyNewProject = StackNavigator(
{
First: { screen: MainActivity },
Second: { screen: SecondActivity }
});
// getting error "undefined is not a function (evaluating '(0 _reactnavigation.stacknavigator)')"..
import React, { Component } from 'react';
import { StyleSheet, Text, View, ListView, ActivityIndicator } from 'react-native';
import { StackNavigator } from 'react-navigation';
class MainActivity extends Component {
constructor(props) {
super(props);
this.state = {
// Default Value of this State.
Loading_Activity_Indicator: true
}
}
componentDidMount() {
return fetch('https://reactnativecode.000webhostapp.com/FruitsList.php')
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
Loading_Activity_Indicator: false,
dataSource: ds.cloneWithRows(responseJson),
}, function() {
// In this block you can do something with new state.
});
})
.catch((errorMsg) => {
console.error(errorMsg);
});
}
ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
Navigate_To_Second_Activity=(fruit_name)=>
{
//Sending the JSON ListView Selected Item Value On Next Activity.
this.props.navigation.navigate('Second', { JSON_ListView_Clicked_Item: fruit_name });
}
static navigationOptions =
{
title: 'MainActivity',
};
render()
{
if (this.state.Loading_Activity_Indicator) {
return (
<View style={styles.ActivityIndicator_Style}>
<ActivityIndicator size = "large" color="#009688"/>
</View>
);
}
return (
<View style={styles.MainContainer}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={(rowData) => <Text style={styles.rowViewContainer}
onPress={this.Navigate_To_Second_Activity.bind(this, rowData.fruit_name)} >{rowData.fruit_name}</Text>}
/>
</View>
);
}
}
class SecondActivity extends Component
{
static navigationOptions =
{
title: 'SecondActivity',
};
render()
{
return(
<View style = { styles.MainContainer }>
<Text style = { styles.TextStyle }> { this.props.navigation.state.params.JSON_ListView_Clicked_Item } </Text>
</View>
);
}
}
export default MyNewProject = StackNavigator(
{
First: { screen: MainActivity },
Second: { screen: SecondActivity }
});
const styles = StyleSheet.create(
{
MainContainer:
{
justifyContent: 'center',
flex:1,
margin: 10
},
TextStyle:
{
fontSize: 23,
textAlign: 'center',
color: '#000',
},
rowViewContainer:
{
fontSize: 17,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10,
},
ActivityIndicator_Style:
{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
left: 0,
right: 0,
top: 0,
bottom: 0,
}
});
// I have tried may thing but not getting the solutions .. I am stuck , this might be small thing but not getting the solutions..
I need help for this ..
Thanks

Try this code
import React, { Component } from 'react';
import { StyleSheet, Text, View, ListView, ActivityIndicator } from 'react-native';
import { createStackNavigator } from 'react-navigation'
class MainActivity extends Component {
constructor(props) {
super(props);
this.state = {
// Default Value of this State.
Loading_Activity_Indicator: true
}
}
componentDidMount() {
return fetch('https://reactnativecode.000webhostapp.com/FruitsList.php')
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
Loading_Activity_Indicator: false,
dataSource: ds.cloneWithRows(responseJson),
}, function() {
// In this block you can do something with new state.
});
})
.catch((errorMsg) => {
console.error(errorMsg);
});
}
ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
Navigate_To_Second_Activity=(fruit_name)=>
{
//Sending the JSON ListView Selected Item Value On Next Activity.
this.props.navigation.navigate('Second', { JSON_ListView_Clicked_Item: fruit_name });
}
static navigationOptions =
{
title: 'MainActivity',
};
render()
{
if (this.state.Loading_Activity_Indicator) {
return (
<View style={styles.ActivityIndicator_Style}>
<ActivityIndicator size = "large" color="#009688"/>
</View>
);
}
return (
<View style={styles.MainContainer}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={(rowData) => <Text style={styles.rowViewContainer}
onPress={this.Navigate_To_Second_Activity.bind(this, rowData.fruit_name)} >{rowData.fruit_name}</Text>}
/>
</View>
);
}
}
class SecondActivity extends Component
{
static navigationOptions =
{
title: 'SecondActivity',
};
render()
{
return(
<View style = { styles.MainContainer }>
<Text style = { styles.TextStyle }> { this.props.navigation.state.params.JSON_ListView_Clicked_Item } </Text>
</View>
);
}
}
export default MyNewProject = createStackNavigator (
{
First: { screen: MainActivity },
Second: { screen: SecondActivity }
});
const styles = StyleSheet.create(
{
MainContainer:
{
justifyContent: 'center',
flex:1,
margin: 10
},
TextStyle:
{
fontSize: 23,
textAlign: 'center',
color: '#000',
},
rowViewContainer:
{
fontSize: 17,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10,
},
ActivityIndicator_Style:
{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
left: 0,
right: 0,
top: 0,
bottom: 0,
}
});

Change your code to this.
import { createStackNavigator } from 'react-navigation';
export default MyNewProject = createStackNavigator(
{
First: { screen: MainActivity },
Second: { screen: SecondActivity }
});

stackNavigator is deprecated, you should use createStackNavigator instead
More info at: https://reactnavigation.org/docs/en/stack-navigator.html
EDIT:
import { createStackNavigator } from 'react-navigation'
export default MyNewProject = createStackNavigator (
{
First: { screen: MainActivity },
Second: { screen: SecondActivity }
});

Related

Add WebView via onClick in Expo React-Native

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

undefined is not an object (evaluating '_this3.props.navigation.navigate')

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.

How to re-render a tab in React-Native

I have a React-Native flashcard app that boots with two tabs, a Home tab, and a New Deck tab. The Home tab is the default, and you can press or swipe over to the New Deck tab.
The Home tab displays all of the decks the user currently has saved.
On the New Deck tab, I have the user enter the title of their new deck and press a submit button. When that submit button is pressed, I re-navigate to the Home tab.
My issue is: How in the world do I trigger a re-render on the Home tab from a button press on the New Deck tab so the user can see the deck they just created?
I know I could use Redux to solve this issue, but no other part of the app is optimized in a "Redux" fashion, and I'd really like to not redesign the architecture of my app for the sole purpose of updating a single screen, mostly because this is the only instance where I would need this ability.
I've attempted to get around this by passing screenProps containing the this.forceUpdate method all the way from the StackNavigator component, but it didn't work. I also tried manually update the state of the App component to trigger a re-render, but the re-render never happened (although the state did update).
App.js
import React, { Component } from 'react'
import { Text, View } from 'react-native'
import AlphaHome from './Components/Home/AlphaHome'
import AlphaQuiz from './Components/Quiz/AlphaQuiz'
import AlphaNewUdaciDeck from './Components/NewUdaciDeck/AlphaNewUdaciDeck'
import AlphaNewUdaciCard from './Components/NewUdaciCard/AlphaNewUdaciCard'
import AlphaUdaciDeckDetails from './Components/UdaciDeckDetails/AlphaUdaciDeckDetails'
import { TabNavigator, StackNavigator } from 'react-navigation'
const Tabs = TabNavigator({
Home: {
screen: AlphaHome,
navigationOptions: {
tabBarLabel: 'Home',
},
},
NewDeck: {
screen: AlphaNewUdaciDeck,
navigationOptions: {
tabBarLabel: 'New Deck',
}
}
}, {
navigationOptions: {
header: null,
},
tabBarOptions: {
activeTintColor: 'white',
indicatorStyle: {
backgroundColor: 'white'
},
style: {
height: 50,
borderBottomColor: 'white',
backgroundColor: 'deepskyblue',
}
},
})
const Stack = StackNavigator({
Home: {
screen: Tabs,
},
AlphaNewUdaciDeck: {
screen: AlphaNewUdaciDeck,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
AlphaNewUdaciCard: {
screen: AlphaNewUdaciCard,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
AlphaUdaciDeckDetails: {
screen: AlphaUdaciDeckDetails,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
})
export default class App extends Component {
render() {
return (
<Stack />
)
}
}
Home.js
import React, { Component } from 'react'
import { ScrollView, View, Text, StyleSheet, AsyncStorage, ActivityIndicator } from 'react-native'
import UdaciDeck from '../Reusable/UdaciDeck'
import { getAllData } from '../../utils/AsyncApi'
export default class HomeExistingUser extends Component {
state = {
decks: null,
}
componentDidMount() {
let decks = getAllData()
setTimeout(() => {
this.setState({
decks
})
}, 1000)
}
showDetails = (title, count) => {
this.props.navigation.navigate('AlphaUdaciDeckDetails', {title, count})
}
render() {
const {decks} = this.state
return (
decks
? <ScrollView contentContainerStyle={styles.container}>
{decks.map(s => <UdaciDeck key={s[1].title} name={s[1].title} count={s[1].questions.length} method={this.showDetails} />)}
</ScrollView>
: <View style={[styles.container, {flex: 1, justifyContent: 'center'}]}>
<ActivityIndicator size='large' color='white' />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
minHeight: '100%',
backgroundColor: 'lightskyblue',
paddingTop: 20,
paddingBottom: 20,
alignItems: 'center',
},
})
NewDeck.js
import React, { Component } from 'react'
import { View, Text, TextInput, StyleSheet, AsyncStorage, TouchableNativeFeedback, Alert } from 'react-native'
import { addDeck } from '../../utils/AsyncApi'
// BUG: when adding a new deck (if HomeExistingUser is true) view doesn't update. Need to figure out a way to update on tab navigate back
export default class AlphaNewUdaciDeck extends Component {
state = {
input: '',
keys: null,
}
componentDidMount() {
AsyncStorage.getAllKeys()
.then(keys => this.setState({
keys
}))
}
handleSubmit = () => {
const {input, keys} = this.state
input.search(' ') > 0 || input.length < 1 || keys.filter(s => s === input).length > 0
? Alert.alert(`Please enter a valid name (${input.length < 1 || keys.filter(s => s === input).length > 0 ? `you can't save a deck with ${input.length < 1 ? 'no' : 'an already used'} name` : "no spaces"})`)
: addDeck(input)
;if(input.search(' ') < 0 || input.length > 0 || keys.filter(s => s === input).length < 1) {
this.props.navigation.goBack()
}
}
render() {
return (
<View style={[styles.container, styles.containerOne]}>
<View style={styles.containerTwo}>
<Text style={styles.text}>Name of the deck</Text>
<Text style={styles.text}>(Please no spaces)</Text>
<TextInput
autoFocus={true}
onChangeText={(input) => this.setState({
input
})}
selectionColor={'deepskyblue'}
underlineColorAndroid={'transparent'}
style={styles.input}
/>
<TouchableNativeFeedback onPress={this.handleSubmit}>
<View style={styles.btn}>
<Text style={styles.btnText}>Save Deck</Text>
</View>
</TouchableNativeFeedback>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'lightskyblue',
},
containerOne: {
alignItems: 'center',
},
containerTwo: {
marginTop: 50,
},
text: {
color: 'white',
fontSize: 20,
},
input: {
backgroundColor: 'white',
height: 50,
width: 300,
marginTop: 15,
fontSize: 20,
paddingLeft: 5,
paddingRight: 5,
color: 'deepskyblue'
},
btn: {
backgroundColor: 'deepskyblue',
marginTop: 50,
padding: 20,
paddingLeft: 50,
paddingRight: 50,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 5,
},
btnText: {
color: 'white',
},
})
You should check out react-navigation-is-focused-hoc at https://github.com/pmachowski/react-navigation-is-focused-hoc to solve the specific problem you mentioned.
You can also try
onNavigationStateChange(prevState, newState)
there is a sample at How can I tell if the screen is navigated to with ReactNavigation

React Native randomly errors: Can't find variable image after 30 - 90 seconds

So I'm building a React Native app using
React Native - Latest
MobX and MobX-React - Latest
Firebase - Latest
My app works fine. However, I can leave the app idle or play around with it and after 30-90 seconds I red screen with this error. Its not being very specific about what file is erroring! How can I debug this?
Firebase.js
export function getFeed(db,id,callback){
db.collection("posts").where("userId", "==", id)
.get()
.then(function (querySnapshot) {
callback(true,querySnapshot)
})
.catch(function (error) {
callback(false)
console.log("Error getting documents: ", error);
});
}
List.js
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableOpacity,
FlatList,
ActivityIndicator,
RefreshControl
} from 'react-native';
import Post from './Post';
import Spinner from 'react-native-spinkit';
import { Icon } from 'react-native-elements';
import { getFeed } from '../../network/Firebase';
import { observer, inject } from 'mobx-react';
#inject('mainStore')
#observer export default class List extends Component {
constructor(props) {
super(props)
this.state = {
dataSource: [],
initialLoad: true,
refreshing: false
}
this.getData = this.getData.bind(this)
}
componentWillMount() {
this.getData()
}
getData() {
this.setState({
refreshing: true
})
getFeed(this.props.screenProps.db, this.props.mainStore.userData.id, (status, res) => {
let tempArray = []
let counter = 0
res.forEach((doc) => {
let tempObj = doc.data()
doc.data().user
.get()
.then((querySnapshot) => {
tempObj.userData = querySnapshot.data()
tempArray.push(tempObj)
counter = counter + 1
if (counter === res.docs.length - 1) {
this.setState({
dataSource: tempArray,
initialLoad: false,
refreshing: false
})
}
})
});
})
}
renderRow = ({ item }) => {
return (
<Post item={item} />
)
}
render() {
if (this.state.initialLoad) {
return (
<View style={styles.spinner}>
<Spinner isVisible={true} type="9CubeGrid" size={40} color="white" />
</View>
)
} else {
return (
<FlatList
data={this.state.dataSource}
extraData={this.state}
keyExtractor={(_, i) => i}
renderItem={(item) => this.renderRow(item)}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this.getData}
/>
}
/>
);
}
}
}
const styles = StyleSheet.create({
spinner: {
marginTop: 30,
alignItems: 'center'
}
});
Post.js
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableOpacity,
Image
} from 'react-native';
import moment from 'moment';
import { Icon } from 'react-native-elements';
export default class Post extends React.PureComponent {
render() {
let today = moment()
let date = this.props.item.date
if(today.diff(date, 'days') < 5){
date = moment(date).startOf('day').fromNow()
}else{
date = moment(date).format('DD MMM YYYY, h:mm a')
}
return (
<View
style={styles.container}
>
<View style={styles.top}>
<Image style={styles.profile} source={{uri: this.props.item.userData.image}} />
<Text style={styles.title}>{this.props.item.userData.firstName+' '+this.props.item.userData.lastName}</Text>
</View>
<View style={styles.descriptionContainer}>
<Text style={styles.description}>{this.props.item.description}</Text>
</View>
<View style={styles.imageContainer}>
<Image style={styles.image} source={{uri: this.props.item.image}} />
</View>
<TouchableOpacity style={styles.commentsContainer}>
<View style={styles.timeFlex}>
<Text style={styles.title}>{date}</Text>
</View>
<View style={styles.commentFlex}>
<Text style={styles.title}>Comments (12)</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
title: {
color: 'white',
backgroundColor: 'transparent'
},
timeFlex: {
flex: 0.5,
alignItems: 'flex-start'
},
commentFlex: {
flex: 0.5,
alignItems: 'flex-end'
},
profile: {
width: 40,
height: 40,
borderRadius: 20,
marginRight: 10
},
descriptionContainer: {
marginBottom: 10,
marginHorizontal: 15,
},
description: {
color: 'rgba(255,255,255,0.5)'
},
commentsContainer: {
marginBottom: 10,
alignItems: 'flex-end',
marginHorizontal: 15,
flexDirection: 'row'
},
imageContainer: {
marginBottom: 10,
marginHorizontal: 15,
height: 180
},
image: {
height: '100%',
width: '100%'
},
top: {
justifyContent: 'flex-start',
margin: 10,
marginLeft: 15,
flexDirection: 'row',
alignItems: 'center'
},
container: {
margin: 10,
backgroundColor: '#243c5e',
borderRadius: 10,
shadowColor: 'black',
shadowOffset: {
width: 2,
height: 1
},
shadowRadius: 4,
shadowOpacity: 0.3
}
});

Button positioning according to wrong View

So all the components I am using were created by me excepting TextInput. In another Navigator route i used the all the components excepting TextInput and they worked as intended. But in this case, some how my Buttom positioning follows Card position and not the outer View
// GoalForm.js
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { Header, Button, Card } from '../components';
import { TextInput } from '#shoutem/ui';
export default class GoalList extends Component {
constructor(props) {
super(props);
}
styles = {
nameGoalContainer: {
flexDirection: 'row'
},
center: {
flexDirection: 'column',
justifyContent: 'center'
},
rightLabels: {
fontWeight: 'bold',
fontSize: 17
}
}
render() {
return (
<View style={{ flex:1 }}>
<Header text="New Goal" color='#3f51b5' />
<Card>
<View style={this.styles.nameGoalContainer}>
<View style={ [this.styles.center, { marginRight: 15 }] }>
<Text style={this.styles.rightLabels}>Title</Text>
</View>
<TextInput
maxLength={30}
placeholder="Buy a new graphics card"
style={{ flex: 3, textAlign: 'center' }}
/>
</View>
</Card>
<Button
text="+"
onPress={ () => { console.log('Hello') } }
size='50'
fontSize='25'
color='#FFD600'
fontColor='white'
style= {{
bottom: 20,
right: 20
}}
/>
</View>
);
}
}
// Card.js
import React, { Component } from 'react';
import { View, Platform } from 'react-native';
class Card extends Component {
constructor(props) {
super(props);
}
generateComponent() {
const { cardStyleAndroid } = this.styles;
const { style } = this.props;
switch (Platform.OS) {
case 'android':
return (
<View style={[ cardStyleAndroid, style ]}>
{ this.props.children }
</View>
);
case 'ios':
return 0;
}
}
render() {
return (
<View>
{ this.generateComponent() }
</View>
);
}
styles = {
cardStyleAndroid: {
elevation: 2,
padding: 10,
backgroundColor: 'white',
marginHorizontal: 10,
marginVertical: 7
}
}
}
Card.propTypes = {
platform: React.PropTypes.string.isRequired,
style: React.PropTypes.object.isRequired,
children: React.PropTypes.object.isRequired
};
export default Card;
// Button.js
import React, { Component } from 'react';
import { View, Platform } from 'react-native';
class Button extends Component {
constructor(props) {
super(props);
}
generateComponent() {
const { cardStyleAndroid } = this.styles;
const { style } = this.props;
switch (Platform.OS) {
case 'android':
return (
<View style={[ cardStyleAndroid, style ]}>
{ this.props.children }
</View>
);
case 'ios':
return 0;
}
}
render() {
return (
<View>
{ this.generateComponent() }
</View>
);
}
styles = {
cardStyleAndroid: {
elevation: 2,
padding: 10,
backgroundColor: 'white',
marginHorizontal: 10,
marginVertical: 7
}
}
}
Button.propTypes = {
platform: React.PropTypes.string.isRequired,
style: React.PropTypes.object.isRequired,
children: React.PropTypes.object.isRequired
};
export default Button;
// Header.js
import React from 'react';
import { View, Text, Platform } from 'react-native';
const generateShadow = () => {
switch(Platform.OS) {
case 'android':
return { elevation: 5 };
case 'ios':
return 0;
}
}
const Header = (props) => {
const { textStyle, viewStyle } = styles;
return (
<View style={ [ viewStyle, { backgroundColor: props.color }, generateShadow() ] }>
<Text style={textStyle}>{ props.text }</Text>
</View>
);
};
Header.propTypes = {
color: React.PropTypes.string.isRequired,
text: React.PropTypes.string.isRequired,
};
const styles = {
textStyle: {
color: 'white',
fontWeight: 'bold',
fontSize: 20
},
viewStyle: {
paddingLeft: 20,
height: 55,
flexDirection: 'column',
justifyContent: 'space-around'
}
};
export default Header;
Can anyone spot what I am missing here? Thanks in advance
I needed to wrap my card component in a View with flex:1

Categories

Resources