【React Native】 axios を使用し、一覧表示する。

##axios

axiosとは、ブラウザやnode.js上で動くPromiseベースのHTTPクライアントです。
DBの情報をバックエンドのApiを叩いて取得する際にオーソドックスな方法になります。

# 完成形
![スクリーンショット 2020-07-08 10.33.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517237/f103d529-46e9-00ba-f6f4-dce4cd33bf2a.png)

現在勉強をかねて、Instagramを模倣してアプリケーションを作成しています。
こちらの表示もバックエンドからaxiosを使用しデータを取得しています。

## 使用技術
- expo
- ReactNative
- JSX

## ファイルディレクトリー
```
---components
      |
      |---- Listitem.js (一つ一つの投稿をコンポーネント化)

--screens
      |
      |---- HomeScreen.js (ホーム画面)

```

# ソースコード
## HomeScreen.js

```javascript

import React, { useState, useEffect } from 'react';
import { StyleSheet, View, FlatList } from 'react-native';
import ListItem from '../components/ListItem';
import axios from 'axios';

//* 今回はDBにFirebaseを使用しています。
const URL = 'https://firestore.googleapis.com/v1/projects/?????/databases/(default)/documents/????';

//* navigationは遷移させるときに必要になるものです。
export default  HomeScreen = ({ navigation }) => {

  //* Hooks の導入
  const [posts, setPosts] = useState([]); 
  // * useEffect 導入 コンポーネントのマウント時に発火させるアクションを宣言
  useEffect(() => { 
    fetchPosts();
  }, []);

  // * Axios getMethods
  const fetchPosts = async () => {
    try {
      const response = await axios.get(URL);
      const arrayPost = response.data.documents;
      setPosts(arrayPost);
      // console.log(arrayPost);  dataの確認
    } catch (error) {
      console.error(error);
    }
  }

  return (
    <View style={ styles.container }>
      <FlatList
        data={ posts }
        renderItem={({ item }) => (
          <ListItem
            item = {item.fields}
            userName={ item.fields.user_name.stringValue }
            userImage={ item.fields.user_image.stringValue }
            imageUrl={ item.fields.urlToImage.stringValue }
            content={ item.fields.content.stringValue }
            onPress={() => navigation.navigate('Article', { article: item })}
          />
        )}
      />
    </View>
  );
}
```

## Listitem.js

```javascript
import React from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';

const ListItem = ({userImage, userName, imageUrl, content, onPress}) => {

  return (
    <View style={ styles.postWrapper } onPress={ onPress }>
      <View style={ styles.topBox }>
        <View style={ styles.topBoxLeft }>
          <View style={ styles.userImage }>
            <Image
            style={ styles.userImage }
            source={{ uri: userImage }}
            />
          </View>
          <Text style={ styles.userName }>{ userName }</Text>
        </View>
      </View>
      <View style={ styles.middleBox }>
        <Image
        style={ styles.middleBox }
        source={{ uri: imageUrl }}
        />
      </View>
      <View style={ styles.bottomBox }>
        <View style={ styles.bottomBoxArea }>
          <View style={ styles.bottomLeftArea }>
            <Icon name="heart-o" size={30} style={styles.icon1}/>
            <Icon name="comment-o" size={30} style={styles.icon2}/>
            {/* 詳細画面に遷移する */}
            <TouchableOpacity onPress={ onPress }>
              <Icon name="send-o" size={30} style={styles.icon3}/>
            </TouchableOpacity>
          </View>
          <View style={ styles.bottomCenterArea }></View>
          <View style={ styles.bottomRightArea }>
            <TouchableOpacity onPress={() => {//action}}>
              <Icon name="bookmark-o" size={30} style={styles.icon4}/>
            </TouchableOpacity>
          </View>
        </View>
        <View style={ styles.bottomTopArea }>
          <Text>{ content }</Text>
        </View>
      </View>
    </View>
  )
}

```

**ここでは、FontAwesome等を使用していますが、一旦そちらの説明は割愛致します。**

# HomeScreen.js 説明
ここで使用しているものは、
1) useState
2) useEffect
3) axios
4) FlatList


### 1) useState
useStateはFunctionコンポーネントで記述する際に、状態の変化を受け取るために使用します。
現在推奨としてfunctionコンポーネントでの書き方のようなので、こちらでは使用しています。
> https://ja.reactjs.org/docs/hooks-effect.html

```javascript

import React, { useState, useEffect } from 'react';

const [posts, setPosts] = useState([]); //からの配列に値を入るように設定

```
### 2) useEffect 
useEffectは、component が mount されたタイミングで api を呼ぶために使用しています。
ページが開かれた際に真っ先に読んで欲しいapiのため、こちらを使用します。

```javascript

import React, { useState, useEffect } from 'react';

  const [posts, setPosts] = useState([]); 
  // * useEffect 導入 コンポーネントのマウント時に発火させるアクションを宣言
  useEffect(() => { 
    fetchPosts();
  }, []);
```
>https://ja.reactjs.org/docs/hooks-effect.html

### 3) axios

```javascript
import axios from 'axios';


  // * Axios getMethods
  const fetchPosts = async () => {
    try {
      const response = await axios.get(URL);
      const arrayPost = response.data.documents;
      setPosts(arrayPost);
      // console.log(arrayPost);  dataの確認
    } catch (error) {
      console.error(error);
    }
  }
```

今回は、**async function** を使用しています。
非同期関数 — AsyncFunction オブジェクトである関数を定義します。非同期関数はイベントループを介して他のコードとは別に実行され、結果として暗黙の Promise を返します。ただし、非同期関数を使用したコードの構文および構造は、通常の同期関数と似たものになります。
>https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function

こちらのtry以降でバックエンドから**配列で[]** 値を取得しています。
そしてそれをuseStateで作成した

```javascript

  const [posts, setPosts] = useState([]); 
```
**第二引数のsetPost関数**の中に格納します。
それにより、
**第一引数であるposts**のなかにdataが格納されます。

### 4) FlatList

```javascript

  return (
    <View style={ styles.container }>
      <FlatList
        data={ posts } //先ほどのdataを指定
        renderItem={({ item }) => (
          <ListItem
            item = {item.fields}
            // こちらはFirebase特有に少し独特です...
            userName={ item.fields.user_name.stringValue }
            userImage={ item.fields.user_image.stringValue }
            imageUrl={ item.fields.urlToImage.stringValue }
            content={ item.fields.content.stringValue }
            onPress={() => navigation.navigate('Article', { article: item })}
          />
        )}
      />
    </View>
  );
```


>https://reactnative.dev/docs/flatlist


上記がHomeScreen.js でのAxiosの使用方法になります。
それをListitemコンポーネントに値を継承させ少しコードをすっきりさせています。



**React Native初心者になるため、何か間違い等あればご指摘お願いします！！！！**