Edit: I'm also struggling with understanding what kind of structure I should be going for and how I should pass the navigator between components etc. If you have any critique or feedback about my code that would also be highly appreciated!
So I'm trying to create a newsfeed from my PHP API (which accepts POST-data and returns JSON). The JSON:
{"status":"OK","news":[{"header":"some header","text":"some text"},{"header":"some other header","text":"some other text"},{"header":"yet another header","text":"some even more text"}]}
I want to fetch this JSON into my React Native app and write out each news post as a view. The idea is pretty much a blog. At the moment what I've tried to do isn't working. I can successfully fetch the JSON, however, I don't know how to successfully get the JSON from get_news() in Main_logic.js to render() in index.ios.js and print each news post out as a seperate view element. Any help would be really appreciated!
Here is the render function in my index.ios.js:
render(){
//Components
const Header = (
<TouchableHighlight
onPress={() => this.toggleSideMenu()}
style={this.state.login_button_press ? styles.hamburger_pressed : styles.hamburger}
onHideUnderlay={this._onHideUnderlay.bind(this)}
onShowUnderlay={this._onShowUnderlay.bind(this)}
>
<View>
<Icon
name='menu'
color='#FFFFFF'
size={40}
/>
</View>
</TouchableHighlight>
)
const ContentView = (
<Navigator
initialRoute={{id: 'news'}}
configureScene={this._configureScene}
renderScene={(route, navigator) => {
//Inloggningssidan
if(route.id === "login"){
return(
<View style={{opacity: this.state.opacity}, styles.container}>
<Image resizeMode="center" style={styles.logo} source={require('./app/res/mbab_cmyk.png')} />
<TextInput
placeholder="Namn"
autocorrect={false}
style={styles.text_box}
onChangeText={(username) => {{GLOBALS.USERNAME = username}}}
returnKeyType="next"
onSubmitEditing={(event) => {
this.refs.password.focus();
}}
/>
<TextInput
ref="password"
placeholder="Lösenord"
autocorrect={false}
secureTextEntry={true}
style={styles.text_box}
onChangeText={(password) => {{GLOBALS.PASSWORD = password}}}
returnKeyType="go"
/>
<TouchableHighlight style={styles.login_button} onPress={() => MainLogic.login(navigator)}>
<Text style={styles.button_text}>Logga in</Text>
</TouchableHighlight>
</View>
);
}
else if(route.id === "news"){
var news = MainLogic.get_news();
return(
<ScrollView style={{opacity: this.state.opacity}, styles.scroll_container}>
<Text style={styles.empty_text}>{news}</Text>
</ScrollView>
);
}
//Test sida
else{
return(
<View style={styles.container}>
{Header}
<Text>TEST</Text>
<TouchableHighlight style={styles.button}>
<Text>Tryck på mig</Text>
</TouchableHighlight>
</View>
);
}
}
}
/>
)
//App
return (
<View style={{backgroundColor: "#093360", flex: 1}}>
<View style={{flex: 1, marginTop: 20}}>
<StatusBar
barStyle={"light-content"}
/>
<SideMenu
isOpen={this.state.sidemenu_is_open}
style={styles.menu}
menu={<this.Menu navigator={navigator}/>}
>
<View style={styles.header_bar}>
{Header}
</View>
{ContentView}
</SideMenu>
</View>
</View>
);
}
I also try to split up my code into components to keep it in a pleasant structure. Index.ios.js:
import GLOBALS from './app/components/globals.js';
const MainLogic = require('./app/components/logic/main_logic.js');
Here is the function get_news() located in Main_logic.js (MainLogic):
get_news: function(){
fetch(GLOBALS.API_URL, {
method: "POST",
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: "function=news&username=" + GLOBALS.USERNAME + "&password=" + GLOBALS.PASSWORD,
})
.then((response) => response.json())
.then((response) => {
try{
if(JSON.stringify(response.status).replace(new RegExp('"', 'g'), '').match("OK")){
GLOBALS.NEWS = response;
}
else{
return "FEL";
}
}
catch(e){
AlertIOS.alert("error", e.message);
}
})
.catch((e) => {
console.warn(e);
})
.done();
}
Edit: In response to amb:
news.js:
import React, { Component } from 'react';
import {
View,
Text,
TouchableHighlight,
ListView,
} from 'react-native';
import styles from './styles.js';
import GLOBALS from './globals.js';
const MainLogic = require('./logic/main_logic.js');
export default class News extends Component{
constructor (props) {
super(props)
this.state = { news: [] }
}
componentDidMount(){
// Modify your function to return a promise instead of a value
MainLogic.get_news().then(response => {
// setState will trigger a render with the received data
this.setState({news: response});
})
}
_renderRow(rowData, sectionID, rowID, highlightRow){
return (
<View>
<Text>{rowData}</Text>
</View>
)
}
render(){
return (
<ListView
dataSource={this.state.news}
renderRow={this._renderRow()}
/>
);
}
}
get_news() in main_logic.js:
get_news: async function(){
fetch(GLOBALS.API_URL, {
method: "POST",
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: "function=news&username=" + GLOBALS.USERNAME + "&password=" + GLOBALS.PASSWORD,
})
.then((response) => response.json())
.then((response) => {
try{
if(JSON.stringify(response.status).replace(new RegExp('"', 'g'), '').match("OK")){
return response.news;
}
else{
return "FEL";
}
}
catch(e){
AlertIOS.alert("error", e.message);
}
})
.catch((e) => {
console.warn(e);
})
.done();
}
Getting error undefined is not an object (evaluating 'allRowIDs.length')