ios - React Native - 从 fetch() JSON 渲染多个元素?

标签 ios reactjs react-native

编辑: 我也在努力理解我应该采用什么样的结构以及我应该如何在组件之间传递导航器等。如果您对我的代码有任何批评或反馈,也将受到高度赞赏!

因此,我尝试从 PHP API 创建新闻源(它接受 POST 数据并返回 JSON)。 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"}]}

我想将此 JSON 提取到我的 React Native 应用程序中,并将每条新闻文章写为 View 。这个想法几乎就是一个博客。目前我尝试做的事情是行不通的。我可以成功获取 JSON,但是,我不知道如何从 Main_logic.js 中的 get_news() 成功获取 JSON 到 render()index.ios.js 中并将每个新闻帖子打印为单独的 View 元素。任何帮助将不胜感激!

这是我的 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>
    );
  }

我还尝试将我的代码拆分成多个组件,以使其保持在一个令人愉快的结构中。索引.ios.js:

import GLOBALS from './app/components/globals.js';
const MainLogic = require('./app/components/logic/main_logic.js');

这是位于 Main_logic.js (MainLogic) 中的函数 get_news():

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();
  }

编辑: 回应 amb:

新闻.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()}
      />
    );
  }
}
main_logic.js 中的

get_news():

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();
  }

获取错误 undefined is not an object (evaluating 'allRowIDs.length')

最佳答案

var news = MainLogic.get_news(); 是一个异步调用,所以如果你不等待它完成,你的 news 将永远不会有任何内容变种。

这个 block

var news = MainLogic.get_news();
return (
  <ScrollView style={{opacity: this.state.opacity}, styles.scroll_container}>
    <Text style={styles.empty_text}>{news}</Text>
  </ScrollView>
);

永远不会呈现任何消息。

您应该做的是让一个组件调用 get_news 函数并在响应到达时更改其状态。以此伪代码为例,按照注释注释:

class News extends React.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})
    }
  }

  render () {
    // You should use ListView instead of ScrollView, because
    // this.state.news will be an array and it can't be displayed
    // in a Text component.
    return (
      <ScrollView style={{opacity: this.state.opacity}, styles.scroll_container}>
        <Text style={styles.empty_text}>
          {this.state.news}
        </Text>
      </ScrollView>
    )
  }
}

关于ios - React Native - 从 fetch() JSON 渲染多个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41238259/

相关文章:

ReactJS componentWillUnmount 未在路由更改时调用

javascript - REACT - 将选择从下拉列表转换为标签标签

ios - 在真实设备中调用方法 'FirebaseApp.configure()'时,应用程序崩溃

ios - 快速将 JSON 转换为 ManagedObject 以获得可选参数

ios - UICollectionView 重新排序 : interactive movement or drag and drop?

javascript - 即使我使用 React.js 映射包含 1,000 个对象的数组,如何一次仅将 25 个对象渲染到屏幕上

ios - 远程构建 iOS 应用程序

javascript - 传递 props 时我应该总是写 this.props 吗?

javascript - React Native 图像替换为空白 "document"图像

react-native - 开发服务器返回响应错误代码: 500 in react-native