React Nativeでアプリ開発前に知りたかったこと
React Nativeでアプリをリリースして、作る前に知りたかったRN特有の難しさをシェアです〜
記事の内容の前に宣伝です!!
摂取カロリー・栄養素管理アプリをリリースしました!
少しでも興味がある方はインストールしてみてください〜✌️
iOS: https://apps.apple.com/jp/app/silent-flame/id1556855885
Android: https://play.google.com/store/apps/details?id=com.silentflame
使い方: https://note.com/esuke/n/n9f64c4d6c112
環境について
内容に入る前に、今回のReact Native(RN)の開発環境について、
- react-native-cliで作成
- Package Version
- react: "16.13.1"
- react-native: "0.63.4"
- typescript: "4.1.3"
- react-native-firebase: "10.7.0"
- other
- Functional Component
- tsx
- mac
ライブラリ導入関連
ライブラリの追加でエラーがでがち
新しいライブラリを入れた時に結構な頻度でエラーが出ます。
私の場合は、どうやらストレージ管理に使おうと思っていたReamでいつもエラーが出ていました。
原因はバグのようでしたが、アンインストールした後もちょこちょこエラーが出ていました。
エラーが出た場合は下記のコマンドで再インストールすることで、エラーが解決できます。
package.jsonに登録するととても便利でした。
RN
rm -rf node_modules && rm yarn.lock && yarn && yarn start -- --reset-cache
iOS
まず、xCodeで"Clean Build Folder"を実行、
その後コマンドを実行。
rm -rf ios/Pods && rm ios/Podfile.lock && npx pod-install && yarn ios
Android
rm -rf android/app/build && cd android && ./gradlew clean && yarn android
それでも解決しない場合は、xCode, Android Studioでエラー内容を確認し、解決する必要があります。
例えば、info.plistやbuild.gradleでの記述漏れなどがある場合です。
Manual Linkingをしないほうがいい
特別な理由がない限りManual Linkingをしないほうがいいです。
私がRNを初めて触ってから2年くらいたち、久しぶりに触りましたが、React Native 0.60から実装されたAutolinkingが便利すぎます。
Autolinkingのおかげで、react-native-cliでの開発が一気に楽になった気がします。
多くのライブラリはAutolinkingに対応していますが、中にはメンテがされていないせいで、対応していないライブラリがあります。
Autolinkingに対応していないライブラリを使いたくて試しに、Manual Linkingの方法でインストールしましたがうまく入らず、断念しました。
また、Firebase関連のライブラリは不安定という話をよく聞くので、Manual Linkingしてインストールしてみましたが、うまく動かず、Autolinkingの方法で再インストールしてうまく動くようになりました。
特別な理由がない限り、Autolinkingに対応しているライブラリをAutolinkingの方法でインストールするのが良さそうです。
プラットフォーム間の違い
Buttonは使いにくい
iOSとAndroidで表示が変わるため、デザインをプラットフォーム間で同じにする場合は使う必要はなさそうです。
iOS
Android
TouchableOpacity、TouchableHighlightでイベントが取れないケース
VSCodeを使っている場合に起きがちなのかもですが、パッケージを自動的に追加した際に、
import {TouchableOpacity, TouchableHighlight} from "react-native-gesture-handler"
が追加されていることがあります。
想定していた追加はこっち
import {TouchableOpacity, TouchableHighlight} from "react-native"
react-native-gesture-handler
では、ネイティブ側で処理されるため、onPress
が取れません。(iosが取れるが、androidは取れない)
特にボタンを押した時に挙動が関係ないような、遷移用のボタンなどは、react-native-gesture-handler
に同じコンポーネントが存在しないPressable
が紛らわしくなくていいでしょう。
androidはタブレットに対応しないといけない
今回、iOSを先行して開発していて、Android側の挙動は確認していませんでした。
iOSが完成して、さくっと出せそうならAndroidもだそうと思い、挙動を確認したところ、特に問題がなく、意気揚々とリリースしようとしたら、、、
google play consoleで、タブレット用のスクリーンショットが必要と警告が出ていました。
iOSではipadの対応を切っているため、iPhoneの多少違う幅と高さに対応しただけだったので、タブレットで表示するととてもみれるものではなかったです😅
とりあえず、そのまま出しましたが、どうせならipadにも対応したレスポンシブ設計にすべきだったかなと思います。
ちなみにAndroidではタブレットのリリースを切る設定は簡単なものはないようです。
Other
textタグはラッパーして使ったほうがいい
OSに設定されている文字サイズによって、フォントサイズ が変化するため、その設定の影響を受けないような設定が必要。
全てのtextタグに属性をつけるのは面倒なので、textタグはラッパーして使ったほうが使いやすい
こちらのAccessibility (A11y) Walk-throughs
に詳しい説明があります。
recoilの設計は慎重に
今回は、state管理にrecoilを使いました。
recoil自体は使いやすいものでおすすめできるものですが、ストレージの保存に用いる際は少し注意が必要でした。
実際のコードはこんな感じ、
editableState
(変更可能)がtrue
の場合にのみ、supplis
をストレージに保存するという処理です。
supplisState
(サプリの情報を格納)に、画面側で入力されたサプリ情報が格納されるわけですが、アプリを開いた時にもこのstate更新されるため、そのタイミングでeditableState
を適切に切り替える必要がでで、調整が大変しでした。
(アプリの仕様上、当日以外のデータは変更できないようになっています。)
export const supplisState = atom<Suppli[]>({
key: 'supplsState',
default: [],
});
export const editableState = atom<boolean>({
key: 'editableState',
default: true,
});
export const isSaveSupplisState = selector({
key: 'isSaveSupplisState',
get: ({get}) => {
const supplis = get(supplisState);
const editable = get(editableState);
if (editable) {
storageSave('mySuppli', supplis);
return true;
}
return false;
},
});
今考えると、supplisState
の役割を、
-
supplisInitState
(初期値を呼び出し、state hookで十分そう) -
supplisEditableState
(編集○ -> supplisInitStateの値を移す) -
supplisReadOnlyState
(編集✖️ -> supplisInitStateの値を移す)
に分たほうが、ロジックもわかりやすかったかなと思います。
recoilのselectorには1つのatomのみを使うほうが後々楽そうです。
キーボード表示のスクロール制御がむずい
フォーム画面でreact-hook-form
を使いましたが、このライブラリとmodalを組み合わせ他のが失敗でした。
今回、TextInputタグをタップしたときにmodalを表示し、タップしたbutton要素によって、自動で入力値を決定するような仕様にしました。
コードはこんな感じ、
Keyboard.dismiss();
でキーボードが表示された瞬間に隠すということをしています😅
これ自体は個人開発では目をつぶれそうなものでしたが、modalを表示させると、そっちに全画面の高さが持っていかれるせいか、modalが消えた瞬間に自動的に画面が一番上にスクロールされちゃっています。
<Controller
control={control}
render={({onChange, onBlur, value}) => (
<>
<TextInput
style={[
styles.input,
shadowStyles('black').boxShadow,
errors[`${index}nutrientName`] ? styles.invalid : styles.valid,
]}
onBlur={onBlur}
onChangeText={(v) => onChange(v)}
value={value}
placeholder="栄養素名"
placeholderTextColor="lightgray"
editable={formType === 'water' && index === 0 ? false : editable}
onFocus={() => {
Keyboard.dismiss();
setIsScroll(false);
setModalVisible(true);
}}
/>
<NutrientNameModal
modalVisible={modalVisible}
setModalVisible={setModalVisible}
nutrientNameValue={value}
nutrientNameOnChange={onChange}
/>
</>
)}
name={`${index}nutrientName`}
rules={{required: true}}
defaultValue={nutrient ? nutrient.nutrientName : ''}
/>
自動スクロールはよくスマホアプリみる機能ですが、難しいことをしようとすると意外と調整が難しく、現状、勝手によくわからない自動スクロールがある状態でリリースしています。
最後に
個人開発でガッツリ開発してみると学びが多く、いいものですね〜✌️
ここまで読んでくれてありがとうございます☺️
記事の内容を読んでアプリの機能には興味がなくてもどんな感じなのか気になるかたのインストールも大歓迎です!!
iOS: https://apps.apple.com/jp/app/silent-flame/id1556855885
Android: https://play.google.com/store/apps/details?id=com.silentflame
使い方: https://note.com/esuke/n/n9f64c4d6c112
Author And Source
この問題について(React Nativeでアプリ開発前に知りたかったこと), 我々は、より多くの情報をここで見つけました https://qiita.com/ebiyy/items/4e51332b2d2b38eac211著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .