React Native ElementsをVue Nativeで使う場合に気をつけること - inokawablog

    React Native ElementsをVue Nativeで使う場合に気をつけること

    公式サイトではReact Nativeの形で書かれているのでそのままではVue Nativeでは使用することができません。

    なのでReact NativeからVue Nativeに変換をします。

     

    まず、React Native Elementsをインストールしましょう

    yarn add react-native-elements

     

     

    例でアバター一覧を表示させてみます。

    まずReact Native Elemetsの公式に記載されているReact Nativeのコード

    import { ListItem } from 'react-native-elements'
    
    const list = [
      {
        name: 'Amy Farha',
        avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg',
        subtitle: 'Vice President'
      },
      {
        name: 'Chris Jackson',
        avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
        subtitle: 'Vice Chairman'
      },
    ]
    
    <View>
      {
        list.map((l, i) => (
          <ListItem
            key={i}
            leftAvatar={{ source: { uri: l.avatar_url } }}
            title={l.name}
            subtitle={l.subtitle}
          />
        ))
      }
    </View>

    React Nativeではこれでアバター付きつのリスト一覧を表示できます。

    この場合、アバターの情報が入ったlistから、mapを使って<ListItem>を出力しています。

     

    これをVue Nativeに変換します。

    <template>
      <view class="container">
        <view v-for="(l,i) in list">
          <list-item
            :key="i"
            :leftAvatar="{ source: { uri: l.avatar_url } }"
            :title="l.name"
            :subtitle="l.subtitle"
          >
        </view>
      </view>
    </template>
    
    <script>
    import React, { Component } from 'react';
    import { View,Text } from 'react-native';
    import { ListItem } from 'react-native-elements'
    
    export default {
      components: {
        ListItem
      },
      data: function() {
        return {
          list: [
            {
              name: 'Amy Farha',
              avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg',
              subtitle: 'Vice President'
            },
            {
              name: 'Chris Jackson',
              avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
              subtitle: 'Vice Chairman'
            },
          ],
        };
      },
    };
    </script>
    
    <style>
    .container {
      flex: 1;
    }
    </style>

    こういった形になります。

    v-forを使ってdata:function()で定義したlistをループで出力させています。

    私はVue Native(Vue)の方が書き方がシンプルで好きです。

     

    もう一つ例を出します。React NativeのrenderItemをVue Nativeに変換する場合です。

    まずはReact Nativeのコード

    import { ListItem } from 'react-native-elements'
    
    const list = [
      {
        name: 'Amy Farha',
        subtitle: 'Vice President'
      },
      {
        name: 'Chris Jackson',
        avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
        subtitle: 'Vice Chairman'
      },
      ... // more items
    ]
    
    keyExtractor = (item, index) => index.toString()
    
    renderItem = ({ item }) => (
      <ListItem
        title={item.name}
        subtitle={item.subtitle}
        leftAvatar={{
          source: item.avatar_url && { uri: item.avatar_url },
          title: item.name[0]
        }}
      />
    )
    
    render () {
      return (
        <FlatList
          keyExtractor={this.keyExtractor}
          data={list}
          renderItem={this.renderItem}
        />
      )
    }

     

    これはReact Native独特の書き方ですよね。React Nativeを触っていないで、いきなりこれを見てしまうとよくわからないかもしれませんが、少しさわればわかります。

    これをVue Nativeに変換します。

    <template>
      <view class="container">
        <flat-list
          :keyExtractor="(item, index) => index.toString()"
          :data="list"
          >
          <view render-prop-fn="renderItem" >
            <list-item
              :title="args.item.name"
              :subtitle="args.item.subtitle"
              :leftAvatar="{source: args.item.avatar_url && { uri: args.item.avatar_url },title: args.item.name[0]}"
            />
          </view>
        </flat-list>
      </view>
    </template>
    
    <script>
    import React, { Component } from 'react';
    import { View,Text } from 'react-native';
    import { ListItem } from 'react-native-elements'
    
    export default {
      components: {
        ListItem
      },
      data: function() {
        return {
          list: [
            {
              name: 'Amy Farha',
              avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg',
              subtitle: 'Vice President'
            },
            {
              name: 'Chris Jackson',
              avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
              subtitle: 'Vice Chairman'
            },
          ],
        };
      },
    };
    </script>
    
    <style>
    .container {
      flex: 1;
    }
    </style>

     

    renderItemがテンプレート部分に入り、可読性が上がりました!

    どこを変更したかというと、以下の部分

    <flat-list
          :keyExtractor="(item, index) => index.toString()"
          :data="list"
          >
          <view render-prop-fn="renderItem" >
            <list-item
              :title="args.item.name"
              :subtitle="args.item.subtitle"
              :leftAvatar="{source: args.item.avatar_url && { uri: args.item.avatar_url },title: args.item.name[0]}"
            />
          </view>
        </flat-list>

    React NativeではrenderItemが分離されていましたが、Vue Nativeではrender-prop-fnを使えば関数をテンプレート部分に組み込んで、その要素の中で出力したい要素を展開することができます。

    特徴的なのはargs。このargsの中に引数が入っています。

    あとはやっていることは同じです。

    React Nativeでは豊富なコンポーネントがすでに用意されており、それらを組み合わせるだけでも十分アプリになります。それらの中にはrenderItemを結構使用しているものが多くあります。

    renderItemはReact Nativeではしょっちゅう出てくるのできっとこの変換をすることになると思います。

     

    さらにコンポーネントを指定する場合は、render-propを使って書いたりします。こちらはあまり使用しないです。

     

    以上で終わりです。

    慣れてくるまでこの変換は少し面倒かもしれませんがやっていくうちになれるので頑張りましょう!