BLOG

【動画】ReactNativeでスマホ向けニュースアプリをつくろう!意外とややこしい画面遷移の実装編!

2022-01-21

このブログはロックシステムのYoutubeチャンネル「ロックシステムアカデミーCH」の文字起こしや使用したコードの解説等をしています。
是非動画本編もご覧ください!
よろしければチャンネル登録も宜しくお願い致します!




いよいよReactNativeを使ったニュースアプリも制作も大詰めだよ!
これまでをおさらいすると
・1回目で環境設定
・2回目で画像と文字を表示するコードを書いてみる
・3回目でAPIを実装してニュース記事を表示
まで終わったね!
今回も前回の続きからスタートするからスマホアプリ作りに挑戦したい人は1回目から見て真似してみてね。


3回目でニュース記事を表示できたんだからもう完成じゃないのー?


実は今はニュース記事一覧を表示してるだけで押しても詳細ページには飛ばないんだよ! だから今回やることは3つ、まずは画面のデザインとレイアウトを調整。


そして画面遷移(画面の移動)の機能と詳細ページを作って行こう!


前回は覚えることが多かったけど、それを乗り越えた私には簡単そうだね!
それじゃあ動画を見ながらやってみるよ!


画面遷移といってもいろいろ種類があって意外とややこしいんだよ!
でも動画を真似すればきっとできるから頑張ってね。


コードがうまく実行されない場合以下の方法を試してみてね!
①Ctrl + Sでコードを保存して下さい
②スマホアプリExpoGoを実行中、スマホの端末を振るとリロード出来ます
③Ctrl + Cでexpoの接続を一度切った後、expo start -cコマンドで再起動しましょう
④expoの操作画面で tuunel と LANを切り替えてください
⑤ブログから完成コードをコピーして下さい
⑥全てダメならコメントで聞いてもらえると嬉しいです



・参照したサイト、使用したコマンド、完成コードを以下からお使いください!


参照サイトリンク
numberOfLines (動画01:50あたり)

SafeAreaView (動画04:00あたり)

ReactNavigation公式 (動画05:35あたり)

ReactNavigationのインストール (動画05:45あたり)

StackNavigatorのサンプルコード (動画09:45あたり)

TouchableOpacityのサンプルコード (動画11:53あたり)

画面遷移のサンプルコード (動画14:50あたり)

WebViewのインストール、サンプルコード (動画16:15あたり)

使用したインストール用コマンド(コピペで使ってください!)

①ページの切り替えに必要なReactNavigation
npm install @react-navigation/native@^5.x

②expoで必要なライブラリ
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

③左右にスライドさせた画面遷移にする
npm install @react-navigation/stack@^5.x

完成コードはこちら!上手く実装できなかったら見比べてみよう!
・DetailScreen.js
import * as React from "react";
import { WebView } from "react-native-webview";
import { StyleSheet } from "react-native";
import Constants from "expo-constants";

export default function DetailScreen(props) {
  const { route } = props;
  const { article } = route.params;
  console.log(article);
  return <WebView source={{ uri: article.url }} />;
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: Constants.statusBarHeight,
  },
});
・App.js
import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import NewsScreen from "./screens/NewsScreen";
import DetailScreen from "./screens/DetailScreen";

const Stack = createStackNavigator();

export default App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="ニュース" component={NewsScreen} />
        <Stack.Screen name="詳細ページ" component={DetailScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};
・NewsScreen.js
import React, { useState, useEffect } from "react";
import { StyleSheet, FlatList, SafeAreaView } from "react-native";
import NewsKizi from "../components/NewsKizi";
import Constants from "expo-constants";
import axios from "axios";

const URI = `https://newsapi.org/v2/top-headlines?country=jp&category=entertainment&apiKey=${Constants.manifest.extra.newsApiKey}`;

export default function NewsScreen({ navigation }) {
  const [news, setNews] = useState([]);

  useEffect(() => {
    getNews();
  }, []);

  const getNews = async () => {
    const response = await axios.get(URI);
    setNews(response.data.articles);
  };

  return (
    <SafeAreaView style={styles.container}>
      <FlatList
        data={news}
        renderItem={({ item }) => (
          <NewsKizi
            imageuri={item.urlToImage}
            title={item.title}
            subtext={item.publishedAt}
            onPress={() => navigation.navigate("詳細ページ", { article: item })}
          />
        )}
        keyExtractor={(item, index) => index.toString()}
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
  },
});
・NewsKizi.js
import React from "react";
import { StyleSheet, Text, View, Image, TouchableOpacity } from "react-native";

const NewsKizi = ({ imageuri, title, subtext, onPress }) => {
  var date = new Date(subtext);
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var day = date.getDate();
  var koukaihiduke = year + "年" + month + "月" + day + "日";

  return (
    <TouchableOpacity style={styles.box} onPress={onPress}>
      <View style={styles.moziBox}>
        <Text numberOfLines={3} style={styles.text}>
          {title}
        </Text>
        <Text style={styles.subText}>{koukaihiduke}</Text>
      </View>

      <View style={styles.gazoBox}>
        <Image style={{ width: 100, height: 100 }} source={{ url: imageuri }} />
      </View>
    </TouchableOpacity>
  );
};

export default NewsKizi;

const styles = StyleSheet.create({
  box: {
    height: 100,
    width: "100%",
    borderColor: "lightblue",
    borderWidth: 1,
    flexDirection: "row",
  },

  moziBox: {
    flex: 1,
    padding: 16,
    justifyContent: "space-between",
  },

  gazoBox: {
    width: 100,
  },

  text: {
    fontSize: 16,
  },

  subText: {
    fontSize: 12,
    color: "darkblue",
  },
});

株式会社ロックシステム

「ブラック企業をやっつけろ!!」を企業理念にエンジニアが働きやすい環境をつきつめる大阪のシステム開発会社。2014年会社設立以来、残業時間ほぼゼロを達成し、高い従業員還元率でエンジニアファーストな会社としてIT業界に蔓延るブラックなイメージをホワイトに変えられる起爆剤となるべく日々活動中!絶賛エンジニア募集中。