[更新中] React Native 開発めも

詰まってたところをまとめていきます
React Native + TypeScript + VSCode + Expoで開発しています
実機使ってます

# コードの書き方

## 複数のスタイルを適用する

例: `styles.textBig`と`styles.textBold`の2つのスタイルを`<Text>`に適用させたい

書き方1: スプレッド演算子を使う

```tsx
<Text style={{ ...styles.textBig, ...styles.textBold }}>てきすとだよ</Text>
```

書き方2: 配列にいれる

```tsx
<Text style={[styles.textBig, styles.textBold]}>てきすとだよ</Text>
```

## `navigation.state.routeName`を使うときの型定義

```jsx
type NavigationState = {
  routeName: string;
  key: string;
};

interface Props {
  navigation: NavigationScreenProp<NavigationState, NavigationParams>;
}
```

`NavigationState`を書かないと、`navigation.state`に`routeName`プロパティはないと言われます
なので、`NavigationState`がどんなオブジェクトかを明示する必要があります
`.routeName`とかを使わない場合はいらないです

`state`についての React-Navigation API reference: 
https://reactnavigation.org/docs/en/navigation-prop.html#state-the-screens-current-state-route

React-Navigation + TypeScriptの dev.to 記事
https://dev.to/andreasbergqvist/react-navigation-with-typescript-29ka

## `navigationOptions`の型定義

**注意: もっといい書き方があるかも**

たとえば、画面のタイトルを設定したいときとかはこう書きます

```tsx
HogeScreen.navigationOptions = () => ({
  title: 'ほげ画面',
});
```

このとき、`HogeScreen`の型をこのように書くとTSからおこられます

```tsx
interface HogeProps {
  ...
}

const HogeScreen: React.FC<HogeProps> = props => ({
  ...
})
```

そこで、`HogeScreen`の型を`React.FC`と`NavigationStackScreenComponent`のintersectionとして定義します

```tsx
const HogeScreen: React.FC<HogeProps> & NavigationStackScreenComponent = props => ({
  ...
})
```

## navigationを使う + 型定義

たとえば、`TouchableOpacity`で、別の画面に遷移させたいときは

```js
onPress={() => props.navigation.navigate('AnotherScreen')}
```

と書きます

propsをコンポーネントにわたす方法はこう↓

```js
/* propsにnavigationしかないとき */
const FooComponent = ({ navigation }) => {
  return (
    // 省略
  )
}

/* propsにnavigation以外もあるとき */
import {
  NavigationParams,
  NavigationScreenProp,
  NavigationState,
} from 'react-navigation';

interface Props {
  hogeProp: number;
  navigation: NavigationScreenProp<NavigationState, NavigationParams>
}
const FooComponent = (props: Props) => {
  return (
    // 省略
  )
}
```

React Navigation の docs: https://reactnavigation.org/docs/en/navigating.html
React NavigationをTypeScriptで使う記事: https://dev.to/andreasbergqvist/react-navigation-with-typescript-29ka

## conditional と 2つ以上の関数

```javascript

isFoo ? (hoge(), bar()) : console.log('not foo')
```

カンマでつないで()でくくると三項演算子でも複数の関数が呼べる

## typeの拡張

このような書き方ができます

```ts
ExtendedProps = {
   isDisabled?: boolean,
   isError?: boolean,
   ...
}
// combining two types
type FullProps = BaseProps & ExtendedProps;

// or attaching properties to a type
type FullProps = BaseProps & {
   isDisabled?: boolean,
   isError?: boolean,
   ...
}
```

引用元: https://medium.com/@rossbulat/typescript-react-manipulating-prop-types-ec13f841a550

# React Native の挙動

## ScrollView の `contentContainerStyle` と `style` の違い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/061c2b42-a479-6ab3-a1c0-48ec660bdac2.png)

style: この図のグレーの箱
contentContainerStyle: この図の青いスクロールする中身

StackOverflowのこの記事から翻訳しました
https://stackoverflow.com/questions/52892304/style-vs-contentcontainerstyle-in-scrollview

## ScrollViewが上に戻る

スクロールしても上にﾋｭﾝって戻っちゃう現象
対処方法:
1. `contentContainerStyle`で`paddingBottom`を適当に設定する
2. `style`でScrollViewの高さを設定する 
`height`で指定, flexとかだとうまくいかないことがある

# Expoで困ったところ

## `console.log`を出力してくれない

expoで開発してるのになぜかターミナルで `console.log()` を吐いてくれない状況

**対処法: iPhoneの名前からASCII文字を取り除く**

Settings > General > About > Nameで変更できます
✗「ほげほげのiPhone」
○「hogehoge iPhone」

ソース: https://forums.expo.io/t/not-getting-console-log-with-expo-cli-on-ios-12-1-4-iphone-7/19272/4