「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',
},
});