LoginSignup
0
0

More than 3 years have passed since last update.

【React Native入門】8-1 サンプルアプリの開発 Yahoo!ニュースチェッカー

Posted at

「React Native入門 掌田 津耶乃著」にて動作確認したコードを逐一まとめた記事です。
基本は自分用のメモですので、動作確認したい場合ご利用ください。
ある程度は1記事を更新していき、セッションが切り替わったら別記事に残していこうと思います。

[ P.336〜P.348 ] Yahoo!ニュースのRSSを使おう

全然理解できていないしWebViewのところでエラーになるため
コードのみ載せておきます。

主なニュース画面までは正常通り動作しますが
各ニュースをタップするとエラーになります。
もし原因と対策がわかる方コメントお願いします。

App.js
import React, { Component } from 'react';
import { StyleSheet,  ScrollView, WebView, StatusBar, Alert, TouchableOpacity, Text, View } from 'react-native';
import { Header } from 'react-native-elements';
import { createStackNavigator } from 'react-navigation';

window.DOMParser = require('xmldom').DOMParser;

// RSS名
const site_items = ['主なニュース','国際ニュース','国内ニュース','経済関係','スポーツ','IT関連','科学技術'];

// RSSアドレス
const site_links = [
  'https://news.yahoo.co.jp/pickup/rss.xml',
  'https://news.yahoo.co.jp/pickup/world/rss.xml',
  'https://news.yahoo.co.jp/pickup/domestic/rss.xml',
  'https://news.yahoo.co.jp/pickup/economy/rss.xml',
  'https://news.yahoo.co.jp/pickup/sports/rss.xml',
  'https://news.yahoo.co.jp/pickup/computer/rss.xml',
  'https://news.yahoo.co.jp/pickup/science/rss.xml'
];

let sel_index = 0; // 選択index
let access_url = ''; // 選択url

// サイトの一覧画面
class Home extends React.Component {
  static navigationOptions = {
    title: 'Yahoo News',
    headerStyle: { backgroundColor: '#4169e1', },
    headerTintColor: 'white',
  }
  constructor(props) {
    super(props);
  }
  getView = (item, i) => (
    <TouchableOpacity onPress={ () => this.goNews(i) }>
      <View style={ styles.site }>
        <Text
          style={{ fontSize:32 }}>
          { i+1 }. { item }
        </Text>
      </View>
    </TouchableOpacity>
  );
  goNews = (n) => {
    sel_index = n;
    this.props.navigation.navigate('Genre');
  }
  render() {
    return (
      <View style={ styles.base }>
        <View style={ styles.body }>
          <ScrollView>
            { site_items.map((item, i) => this.getView(item, i)) }
          </ScrollView>
        </View>
      </View>
    );
  }
}

// 選択したサイトのニュース一覧画面
class Genre extends React.Component {
  items = [];

  static navigationOptions = {
    title: site_items[sel_index],
    headerStyle: { backgroundColor: '#00aa00' },
    headerTintColor: 'white',
  }
  constructor(props) {
    super(props);
    this.state = {
      items: [{ title: 'wait...', link: '', pubDate: '' }],
    }

    let items = [];

    fetch(site_links[sel_index]).then((response) => {
      response.text().then((txt) => {
        const parser = new DOMParser();
        const xml = parser.parseFromString(txt);
        let maintitle = xml.getElementsByTagName('title')[0].childNodes[0].nodeValue;
        let elements = xml.getElementsByTagName('item');
        for(let i = 0;i < elements.length;i++) {
          let item = elements[i];
          let title = item.getElementsByTagName('title')[0].childNodes[0].nodeValue;
          let link = item.getElementsByTagName('link')[0].childNodes[0].nodeValue;
          let pubDate = item.getElementsByTagName('pubDate')[0].childNodes[0].nodeValue;
          items[i] = {
            title: title,
            link: link,
            pubDate: pubDate,
          }
        }
        this.setState({ items: items });
      });
    });
  }
  getView = (item, i) => (
    <TouchableOpacity onPress={ () => this.goContent(i) }>
      <View style={ styles.item }>
        <Text style={{ fontSize: 24 }}>{ item.title }</Text>
        <Text style={{ fontSize: 16 }}>{ item.pubDate }</Text>
      </View>
    </TouchableOpacity>
  );
  goContent = (n) => {
    access_url = this.state.items[n].link;
    this.props.navigation.navigate('Content');
  }
  render() {
    return (
      <View style={ styles.base }>
        <View style={ styles.body }>
          <ScrollView>
            { this.state.items.map((item, i) => this.getView(item, i)) }
          </ScrollView>
        </View>
      </View>
    );
  }
}

// 選択したニュースのWebページを表示する画面
class Content extends React.Component {
  static navigationOptions = {
    title: '選択コンテンツの内容',
    headerStyle: { backgroundColor: '#aa0000' },
    headerTintColor: 'white',
  }
  constructor(props) {
    super(props);
    this.state = { html: '' };
    fetch(access_url).then((response) => {
      response.text().then((txt) => {
        let re = /<a class="newsLink" href="([\w-?:./=]+)"/;
        let arr = txt.match(re);
        this.setState({ html: arr[1] });
      });
    });
  }
  render() {
    return(
      <View style={ styles.base }>
        <View style={ styles.body }>
          <WebView
            source={{ uri: this.state.html }}
            javaScriptEnabled={ true }
          />
        </View>
      </View>
    );
  }
}

// ナビゲーション
export default createStackNavigator(
  {
    Home: { screen: Home },
    Genre: { screen: Genre },
    Content: { screen: Content },
  },
  {
    initialRouteName: 'Home',
  }
);

const styles = StyleSheet.create ({
  base: {
    padding: 0,
    flex: 1,
    backgroundColor: '#ddd',
  },
  body: {
    padding: 10,
    flex: 1,
    backgroundColor: '#fff',
  },
  site: {
    margin: 5,
    padding: 10,
    backgroundColor: '#ddd',
  },
  item: {
    margin: 5,
    padding: 10,
    backgroundColor: '#dfd',
  },
});
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0