Hooks時代のRedux分からない人用useStateとuseEffectを使ったAPI通信処理の書き方 GET編

React Native + Expoを使って大学生ながらとある都内のスタートアップでアプリを開発・運用しています。今のこの令和にRedux分からないってエンジニアとしてどうなの?って思われても致し方ないけど分からんもんは分からん。勉強します、すまん。
で、分からないからできませんっていうのは通じない。じゃあどうするかっていうとよく他の入門記事で見る useStateuseEffectを使う。
雑なコードだけど雰囲気だけ。
例えばホーム画面でユーザ一覧を取得したい、みたいな場面を想定する。
通信はAxios使う。逆にそれ以外知らん。


import React, { useState, useEffect } from 'react';  
import axios from 'axios';  
import { ActivityIndicator } from 'react-native';  
import { UserList } from './component';  

const HomeScreen: React.FC = () => {  
  const [users, setUsers] = useState(null)  

  const featchUserList = async () => {  
    await axios(https://sample.com/api/v1/users`).then(result => {  
      setUsers(result);  
    })  
  }  

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

  if (users === null) return (  
    <View>  
      <ActivityIndicator size='large'>  
    </View>  
  )  
  return (  
    <View>  
      {users.map(user => <UserList user={user}>)}  
    </View>  
  )  
}   

まあ、そりゃこう書くしかないよねって感じ。
useStateでusersをnullで初期化してusersがnullの間はローディング画面にしておいてユーザ一覧を全部取得できたらusersに対してmapを使って各要素をUserListコンポーネントに渡していくというだけの話。別にここは独自のコンポーネントじゃなくてもFlatListでも全然良いと思う。ただある程度の規模になるとちゃんとcomponentディレクトリみたいなやつを作ってそこに切り出した方がメンテしやすい。最初はそんなことも分からなくて全部1ファイルにベタガキして後で分離するのが地獄だったっていうのは記しておく。
ちなみになんでfetchUserList関数に切り出したの?useEffetctの中に直接かけばいいじゃんって思った人もいると思うんだけど、これプルリロードでもおそらく使うことになるだろうな、と思ってあえてuseEffectの中に書きませんでした。加えるとこんな感じ。

import React, { useState, useEffect } from 'react';  
import axios from 'axios';  
import { ActivityIndicator, FlatList, refreshControl } from 'react-native';  
import { UserList } from './component';  

const HomeScreen: React.FC = () => {  
  const [users, setUsers] = useState(null)  
  const [refreshing, setRefreshing] = useState(false);  

  const featchUserList = async () => {  
    await axios(https://sample.com/api/v1/users`).then(result => {  
      setUsers(result);  
    })  
  }  

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

  const onRefresh = React.useCallback(() => {  
    setRefreshing(true);  
    featchUserList().then(() => setRefreshing(false));  
  }, [refreshing]);  

  if (users === null) return (  
    <View>  
      <ActivityIndicator size='large'>  
    </View>  
  )  
  return (  
    <View>  
      <FlatList  
        data={users}  
        renderItem={({ item }) =>  
          <UserList user={item} />  
        }  
        keyExtractor={(item, index) => index.toString()}  
        refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}  
      />  
    </View>  
  )  
}   

まあ、こんな感じ?refreshControl使うためにFlatList使いました。
ほとんど公式ドキュメントと同じ書き方。
これとか超シンプルだけどここに認証とかAPIのエラーハンドリングとか追加していくとみるみるうちにファイルが巨大化するわけです。

結論

ReduxとRedux Saga or Redux thunkあたりのミドルウェアを勉強するといいかもやで。
とにかくビジネスロジックはViewから分離するんや、密はあかん。
あと今はTypeScriptはマストらしいからそれもや。型、大事やもんな。
いや、意味分からん、みたいなことあったら遠慮せずTwitterでDMください。
Twitter: https://twitter.com/Katsukiniwa
GitHub: http://github.com/Katsukiniwa