Closed12

React Native 勉強

ttakttttaktt

基本的に↓の動画で勉強
https://www.youtube.com/watch?v=obH0Po_RdWk&t=2501s

動画ではexpoだけど自分はios simulatorでやってみる。

ttakttttaktt

eslintのインストール、設定

$ npm install eslint --save-dev

$ npx eslint --init
You can also run this command directly using 'npm init @eslint/config'.
Need to install the following packages:
  @eslint/create-config
Ok to proceed? (y) y
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JavaScript
The config that you've selected requires the following dependencies:

@typescript-eslint/eslint-plugin@latest eslint-plugin-react@latest @typescript-eslint/parser@latest
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · npm

$ npm i @react-native-community/eslint-config --save-dev

.eslint.jsのextendsを以下に変更

.eslint.js
"extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:react/recommended",
+       "@react-native-community"
    ],

rulesを以下に変更

.eslint.js
"rules": {
+       semi: ["error", "never"],
+      'comma-dangle': ['2', 'never'],
+       'react/jsx-filename-extendsion': [1, { extensions: ['.ts', '.tsx'] }],
+       'no-use-before-define': [
+           'error',
+          { functions: false, classes: true, variables: false },
+     ],
    }

package.jsonのsctiptsを以下に変更

package.json
"scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
+   "lint": "eslint"
  },
ttakttttaktt

prettier(コードフォーマット整形)のインストール、設定

$ npm i --save-dev --sage-exact prettier
$ touch .prettierc.js

.prettierc.jsの中身

.prettierc.js
module.exports = {
    brancketSpacing: true,
    singleQuote: true,
    tabWidth: 2,
    useTabs: false,
    trailingComma: 'none',
    semi: false,
};
ttakttttaktt

アイコンで挫折

expoだと最初から"@expo/vector-icon"があるけどexpoじゃないから、"react-native-vector-icon"をnpm installして↓のサイトを参考に設定した。
https://qiita.com/unotovive/items/7e1740801ae65ee2abd1

そしたら↓のエラーが出てググっても分からなかった。

ERROR  Invariant Violation: "remaind_me" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called., js engine: hermes

一旦expoに切り替えて解決

ttakttttaktt

ViewコンポーネントはHTMLでいうdivタグみたいな感じ

<View>
      <Text></Text>
</View>

SafeAreaViewを使うと、iOSの下のバーとかに自動的にpaddingをつけてくれる。

<SafeAreaView>
      <Text></Text>
</SafeAreaView>
ttakttttaktt

Flatlist

いい感じにリストを作成するためのコンポーネント。
dataプロパティにリストにしたい配列を渡して、renderItemプロパティに渡したコンポーネントに配列の要素を一つずつ渡す。
実際に表示されるのはrenderItemプロパティに渡したコンポーネント。
keyExtractorに固有のidを渡すのはreact nativeが各項目を追跡できるようにするため。(リスト内の項目に変更があった際のレンダリング効率を上げるため)
ItemSeparatorComponentで各項目間の仕切りみたいなのを作れる。

const DATA = [
  {
    id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
    title: 'First Item',
  },
  {
    id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
    title: 'Second Item',
  },
  {
    id: '58694a0f-3da1-471f-bd96-145571e29d72',
    title: 'Third Item',
  },
];

type ItemProps = {title: string};

const Item = ({title}: ItemProps) => (
  <View>
    <Text>{title}</Text>
  </View>
);

const App = () => {
  return (
    <SafeAreaView>
      <FlatList
        data={DATA}
        renderItem={({item}) => <Item title={item.title} />}
        keyExtractor={item => item.id}
        ItemSeparatorComponent={() => <View style={{backgroundColor: 'red', height: 2}} />}
      />
    </SafeAreaView>
  );
};

その他プロパティは以下のリンク
https://reactnative.dev/docs/flatlist#listemptycomponent

ttakttttaktt

renderItemに渡すものはApp()内で変数に格納した方がFlatListコンポーネント自体はスッキリ書ける。

ttakttttaktt

画像関係

Image

画像を表示するためにコアコンポーネント。
ネットワーク画像とデータ画像の場合は、自分で寸法を設定する。

<Image
    source={require("../../assets/upcoming-background.jpg")}
    style={styles.img}
/>

sourseに表示する画像のパス、もしくはurlなど。

ImageBackground

このコンポーネントの中に配置したコンポーネントの背景がsourseプロパティに入れた画像になる。

<SafeAreaView style={styles.container}>
    <ImageBackground
        source={require("../../assets/upcoming-background.jpg")}
        style={styles.img}
    >
        <Text>Upcoming Weather</Text>
  </ImageBackground>
</SafeAreaView>
ttakttttaktt

style

コアコンポーネントに渡すstyleは配列で渡せる。共通styleと独自styleで分ければコード削減に繋がる。

<Text style={[styles.cityName, styles.cityText]}>London</Text>
<Text style={[styles.countryName, styles.cityText]}>UK</Text>

const styles = StyleSheet.create({
  cityName: {
    fontSize: 40,
  },
  countryName: {
    fontSize: 30,
  },
  cityText: {
    justifyContent: "center",
    alignSelf: "center",
    fontWeight: "bold",
    color: "white",
  },
});
ttakttttaktt

必要なパッケージをインストール

$ npm i @react-navigation/native @react-navigation/bottom-tabs
$ npx expo install react-native-screens react-native-safe-area-context

以下のようにすることでページ遷移させるタブを実装できる

import React from "react";
import { View, StyleSheet } from "react-native";
import CurrentWeather from "./src/screen/CurrentWeather";
import UpcomingWeather from "./src/screen/UpcomingWeather";
import City from "./src/screen/City";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";

const Tab = createBottomTabNavigator();

const App = () => {
  return (
    <NavigationContainer>
    <Tab.Navigator
      screenOptions={{
        tabBarActiveTintColor: "tomato",
        tabBarInactiveTintColor: "gray",
        tabBarStyle: {
          backgroundColor: "lightblue",
        },
        headerStyle: {
          backgroundColor: "lightblue",
        },
        headerTitleStyle: {
          fontWeight: "bold",
          fontSize: 25,
          color: "tomato",
        },
      }}
    >
        <Tab.Screen
          name={"Current"}
          component={CurrentWeather}
          options={{
            tabBarIcon: ({ focused }) => (
              <Feather
                name={"droplet"}
                size={25}
                color={focused ? "tomato" : "black"}
              />
            ),
          }}
        />
        <Tab.Screen
          name={"Upcoming"}
          component={UpcomingWeather}
          options={{
            tabBarIcon: ({ focused }) => (
              <Feather
                name={"clock"}
                size={25}
                color={focused ? "tomato" : "black"}
              />
            ),
          }}
        />
        <Tab.Screen
          name={"City"}
          component={City}
          options={{
            tabBarIcon: ({ focused }) => (
              <Feather
                name={"home"}
                size={25}
                color={focused ? "tomato" : "black"}
              />
            ),
          }}
        />
      </Tab.Navigator>
    </NavigationContainer>
  );
};

Tab.Navigator

tabBarActiveTintColor: 現在のタブの色
tabBarInactiveTintColor: その他のタブの色
tabBarStyle: タブ全体にスタイルを当てられる
headerStyle: ヘッダーにスタイルを当てられる
headerTitleStyle: ヘッダーのタイトル文字にスタイルを当てられる

Tab.Screen

options: tabBarIconでタブアイコンを設定できる。focusedは現在そのタブにいるかどうか

ttakttttaktt

ボタン

コアコンポーネントのButtonが使える。

counst Counter = () => {
    let counnt = 0;
    return (
        <View>
            <Button
                color={'red'}
                title={'Increase the count'}
                onPress={() => {
                    count ++
                    console.log(count)
                }}
            />
        </View>
    )
}

color: 色変えれる
title: ボタンに文字つけれる
onPress: タップ時の処理を与えられる

↑のコード例だとcountの表示は変わらないからstateを使わないとダメ

ttakttttaktt

ローディング画面

コアコンポーネントのActivityIndicatorが使える。

import { ActivityIndicator } from "react-native";

const App = () => {
  if (loading) {
      return (
        <View style={styles.container}>
          <ActivityIndicator size="large" color="blue" />
        </View>
      );
    }
    return (
      <NavigationContainer>
        <View></View>
      </NavigationContainer>
    );
}
このスクラップは2023/07/06にクローズされました