【React Native】RSSリーダー


環境

Expo CLI
TypeScript使用…CLIでTypeScript Blankを選択

シュミレーター起動の確認ができたら
必要なパッケージをインストール

react-native-xml2js
react-native-elements

$ npm add react-native-xml2js
$ npm add react-native-elements
App.tsx
// Expo CLI
// TypeScript要選択

import React, { Component } from 'react';
import { FlatList, Linking, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { Header, Tile } from 'react-native-elements'; // $ npm add react-native-elements
import xml2js from 'react-native-xml2js'; // $ npm add react-native-xml2js

// xml適宜変更
const FEED_URL = 'https://news.yahoo.co.jp/pickup/rss.xml';

type Props = {};

type FeedItem = {
  link: Array<string>,
  title: Array<string>,
};

type State = {
  feedItems: Array<FeedItem>,
};

const renderItem = (params: { item: FeedItem }) => (
  <TouchableOpacity onPress={() => Linking.openURL(params.item.link[0])}>
    <View style={ styles.row }>
      <Text style={ styles.title }>{ params.item.title[0] }</Text>
      <Text style={ styles.link }>{ params.item.link[0] }</Text>
    </View>
  </TouchableOpacity>
);

export default class App extends Component<Props, State> {
  state = {
    feedItems: [],
  }

  componentDidMount() {
    fetch(FEED_URL)
      .then(res => res.text())
      .then((xml) => {
        const parser = xml2js.Parser();
        parser.parseString(xml, (err, result) => {
          this.setState({ feedItems: result.rss.channel[0].item });
        });
      });
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={ styles.base }>
            <Header
                centerComponent={{
                    text: 'RSSリーダー',
                    style: styles.header
                }}
            />
        </View>
        <FlatList
          ItemSeparatorComponent={ () => <View style={ styles.separator } />  }
          data={ this.state.feedItems }
          renderItem={ renderItem }
          keyExtractor={ item => item.link[0] }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  base: {
    padding: 0,
  },
  body: {
      backgroundColor: '#fff',
  },
  header: {
    color: '#fff',
    fontSize: 20,
    fontWeight: '500',
  },
  container: {
    flex: 1,
    backgroundColor: '#FFF',
  },
  row: {
    flex: 1,
    padding: 20,
  },
  title: {
    color: '#000',
    fontSize: 16,
  },
  link: {
    color: '#db7093',
    fontSize: 12,
  },
  separator: {
    flex: 1,
    height: 1,
    backgroundColor: '#ddd',
  },
});