React Native、Redux、Railsを使って、掲示板アプリを作ってみよう

React Native、Redux、Railsを使って、掲示板アプリを作ってみよう

React Native、Redux、Railsを使って、掲示板アプリを作ってみよう

React Native、Redux、Railsを使って、掲示板アプリを作ってみよう へのコメントはまだありません

はじめに

前回、React NativeをAndroid Studioと組み合わせてインストールし、HelloWorldを出せるところまで
たどり着きました。

今回は一足飛びで、React NativeとReduxをフロントエンドに使い、バックエンドにRailsを用いた
掲示板アプリを作ってみましょう。
前提として、Railsはそれなりにわかっている。Reactもよく分かっている。Reduxも知っている。
ぐらいのレベルを前提にしています。

出来上がったアプリは、デザイン的にどんくさいですが、これは私がまだReactNativeの
スタイルの方法を学んでいないためです。まぁそれはおいおいブラッシュアップすることとしましょう。

ソースはすべてGitHubで公開しています。利用方法など含めて、記事の最後に記載しておきます。

機能一覧

  • 掲示板一覧が表示される
  • 掲示板を選択したら、対象のコメント一覧が表示される
  • コメントを投稿できる

機能はこの3つだけ。掲示板も追加できたほうがいいのでしょうが・・
あまり欲張ってあれこれ実装すると、なにを説明しているかわからなくなるので、今回は
カットしておきましょう。

出来上がりのイメージからパーツ構成を考える

出来上がりの画面イメージは以下のようなものです。いかにもどんくさい画面ですが、
これは私がReact Nativeのスタイルの作法がわかっていないためですので、勘弁ください。
rn-31

とりあえず、この画面イメージから、どんなパーツ(Reactのコンポーネント)が必要となるか
考えてみましょう。ざっと以下のようなイメージになると思います。
rn-30

アプリが持つべき、ステートとイベントを考える

画面パーツは考え終わったので、次にアプリが持つステートとイベントを考えましょう。

ステート

  • 現在アクティブな掲示板
  • アクティブな掲示板に投稿されたコメント群
  • 投稿ユーザー
  • 投稿コメント
  • CSRF Token

大体この5つとなります。
投稿ユーザーと投稿コメントは、ステートにしなくても良いのかもしれませんが、Redux風に記述しようとすると
ステートとした方が処理しやすいので、ステートとします。
CSRF Tokenとは、バックエンドのRailsサーバーに対してPOST処理をするときに必要となる認証用のキーみたいなものです。
とりあえず、必要なんだなぁ・・・ぐらいに考えておいてください。

イベント

  • 掲示板を選択する
  • 投稿ユーザーを選択する
  • 投稿コメントを入力する
  • 掲示板にコメントを投稿する

投稿ユーザーの選択とは、本来の掲示板の機能では必要ではありませんが、
ログイン処理などを設けない、今回説明するこのアプリでは、投稿のたびに「私は誰ですよ」と
ユーザーも選択して、コメントを投稿することにします。

バックエンドであるRailsサーバーに必要な機能

バックエンド(サーバーサイド)のRailsアプリに必要な機能をリストアップしてみましょう。

  • 掲示板一覧を取得
  • 投稿ユーザー一覧を取得
  • 対象掲示板のコメント一覧を取得
  • コメントを投稿

Railsでバックエンド処理を実装する

Railsは分かっている前提ですので・・、ざーーっと説明します。

目標となるファイル構成は以下のような感じです。
rn-32
まずはRailsプロジェクトと、React Nativeプロジェクトの親フォルダを作りましょう。
[bash]
$ cd
$ mkdir workspace
$ cd workspace
$ mkdir reactnative_rails_board
[/bash]

Railsプロジェクト作成

[bash]
$ cd reactnative_rails_board
$ rails new rnative_rails
[/bash]

Gemファイルを調整して、bundle install

[bash]
$ cd rnative_rails
$ nano Gemfile
[/bash]

末尾に1行追記
[bash]
gem ‘therubyracer’, platforms: :ruby
[/bash]

動作確認

bundle install して、Railsサーバー起動
[bash]
$ bundle install
$ rails s
[/bash]

ここまでのところを動作確認します。
ブラウザーで

http://localhost:3000

にアクセスしてください。以下のような画面が出れば成功です。
rn-33

モデル作成、サンプルデータ作成

Railsのモデルを作成し、サンプルデータをSeedファイル(CSV)として読み込める状態にしましょう。

モデルの作成
[bash]
$ rails g model board title:string description:text
$ rails g model user name:string sex:integer age:integer
$ rails g model comment board_id:integer user_id:integer comment:text
[/bash]

モデルの調整

rnative_rails/app/models/comment.rb
[bash]
class Comment < ApplicationRecord belongs_to :user end [/bash] マイグレート [bash] $ rake db:migrate [/bash] 出来上がったイメージはこんな感じ。 rails-1

Seedデータの作成

何もないところからデータ投稿までつくり上げるのには時間がかかるので、シード(seed)データを
作っておいて、まずはそのデータを読んで、一覧表示することぐらいから始めましょう。

db/csv/boards.csv
[bash]
1,ReactJSを学ぼう,あいうえお
2,ReactJS と Rails連携,かきくけこ
3,ReactJS 発展編,さしすせそ
4,jQuery入門,たちつてと
5,jQuery得意な人集まれ,なにぬねの
6,AngularJS入門,はひふへほ
7,vue.jsってなんぞ,まみむめも
[/bash]

db/csv/users.csv

[bash]
1,花子,2,23
2,太郎,1,30
3,幸次郎,1,15
4,浩輝,1,40
5,大樹,1,35
6,すず,2,28
7,雅代,2,38

[/bash]

db/csv/comments.csv

[bash]
“1”,”1″,”2″,”ReactはFacebookが開発しているUI(MV*フレームワークでいうViewのようなもの)に特化したJavaScriptライブラリです。 ”
“2”,”1″,”3″,”大きな特徴としてVirtual DOM(仮想DOM)と呼ばれるレンダリング機構がそなわっており、Webページの表示を従来の .”
“3”,”1″,”3″,”公式サイトに、「A JavaScript library for building user interfaces」とあるように、React.jsはUIを構築するためのライブラリです。”
“4”,”1″,”3″,”フレームワークでなくあくまでUIを構築するだけのライブラリで、MVCでいうところのVのみの機能を提供します。”
“5”,”1″,”7″,”最近フロントエンドでfacebook/reactをずっと使っている。世界的には一部のエンジニアの間で流行っているのだが、国内だとqiitaのタグ等を見てもどうも少ない。”
“6”,”2″,”7″,”はじめにreact-railsという、ReactをAsset Pipelineに乗せて使えるようにしてくれるruby gemsがある。 この記事では、これを使用してReactの公式tutorialを進めていく。”
“7”,”2″,”4″,”既存のRailsプロジェクトの中でReact.jsを利用する機会があったので、その時にやったことについてまとめてみます。 私自身は普段RailsのサーバサイドとCoffeeScriptが中心で、最近のJavaScript開発環境についてあまりキャッチアップでき”
“8”,”2″,”5″,”RailsでSingle-Page Applicationをつくるときの自分のやり方をまとめてみます。 Gem 「JavaScriptで書かれたReactのコンポーネントからHTMLを生成する」というのをRubyでやるために、RubyのV8エンジン実装で ..”
“9”,”2″,”2″,”react-railsというReact.jsをRailsに簡単に統合できるgemを使い、React.jsについて説明します。 次のような画面をReact.jsで実装し、Reactとサーバ(Rails)間でメッセージ一覧の取得や作成をできるようにします。 ソースコードはこちらです。”
“10”,”3″,”2″,”最近のモダンなウェブフレームワークと言えば、React+Reduxですよね。でも、なんか難しそうとか、ReactってPHPみたいにViewにロジック混ざりそうとか感じて尻込みしていませんか?それはただの誤解かもしれません。React+Reduxはそんなに難易度の高い .”
“11”,”3″,”1″,”玉石混合状態にあったFluxのフレームワークも、ここ最近ではReduxが首一つ抜け出したような感じとなっています。自分はFacebook/Flux派ではありましたが、先月発売された『WEB+DB PRESS vol.92』に掲載されていた”
“12”,”3″,”6″,” React.jsとReduxを組み合わせた構成で、Webサイトを作ってみるチュートリアル(React+Redux入門)です。第一回目は、GitHub上のコードが読めるようになることを目標に解説しています。”
“13”,”3″,”3″,”目的 ReduxとES6への入門。 React.jsを(ようやく)触る機会が出て、情報量の多いFluxxorとCoffeeScriptで入門してた。 ”
“14”,”7″,”3″,”私たちはなぜReactではなくVue.jsを選んだのか Qwintryチームは最近、既存のすべてのプロジェクトのフロントエンドをVue.jsに移行しはじめました。”
“15”,”6″,”4″,”AngularJS(アンギュラージェイエス)、または Angular は、Googleと個人や企業のコミュニティによって開発されている、完全にJavaScriptで書かれたオープンソースのフロントエンドWebアプリケーションフレームワークである。MIT Licenseでライセンスされた”
“16”,”4″,”4″,”今後のWebデザイナーは、デザイン・htmlコーディング+その他の強みを求められる世の中になっていきます。今回はその強みとなりうる「jQuery」についてご説明いたします。”
“17”,”4″,”2″,”今回はjQueryの基本的な書き方として、これから「jQueryを覚えて、ブイブイ言わせてやるぜ!」と新しいスキルを身につけたいデザイナーさんには丁度いい内容かと思います。”
“18”,”5″,”2″,”今年2016年6月9日、ついに正式版がリリースされた jQuery 3。メジャーバージョンアップしたjQuery 3では、従来のバージョンから、いったい何が変わったのかを2回に分けて解説します。”
“19”,”5″,”1″,” jQueryはWeb業界の発展に大いに役立ってきました。しかし、ネイティブのJavaScriptが高度化し、かつマーケットシェアの縮小した古いブラウザをサポートする必要の薄れた現代において、jQueryを本当に使う必要があるでしょうか?必要性と”
“20”,”4″,”1″,”Webデザイナーやマークアップエンジニアのための超コンパクトなjQuery講座ができました。JavaScriptの予備知識は不要。Web制作に必要な要点だけを解説します。 (1/6)”
“21”,”7″,”6″,”双方向データバインディングに特化したVue.jsは、シンプルで学習コストも低いといわれます。第1回目はVue.jsがフレームワークとして、どんな強みをもっているのか”
“22”,”7″,”7″,”Angular、Reactと並んで海外で人気が高まっている「Vue.js」。ReactとAngularの開発経験がある著者がVue.jsをサンプルコードつきのチュートリアルを通じて特徴をまとめて解説します。2017年、新しく学び始めるきっかけにどうぞ。”

[/bash]

Seedデータをデータベースに反映するスクリプト

db/seeds.rbを編集

[bash]
require ‘csv’

CSV.foreach(‘db/csv/boards.csv’) do |row|
Board.create!(id: row[0], title: row[1], description: row[2])
end

CSV.foreach(‘db/csv/users.csv’) do |row|
User.create!(id: row[0], name: row[1], sex: row[2], age: row[3])
end

CSV.foreach(‘db/csv/comments.csv’) do |row|
Comment.create!(id: row[0], board_id: row[1], user_id: row[2], comment: row[3])
end

[/bash]

Seedデータの投入

[bash]
$ rake db:seed
[/bash]

バックエンドAPI用 AJAXコントローラー作成

[bash]
$ rails g controller board
[/bash]

コントローラーにAPI実装
rnative_rails/app/controllers/board_controller.rb

*readBoardAndUser
起動時に掲示板一覧とユーザー一覧を取得
*insertComment
コメントを投稿
*readComments
選択された掲示板に投稿されたコメント一覧を取得
X-CSRF-Tokenも返しています。

rnative_rails/app/controllers/board_controller.rb
[bash]
class BoardController < ApplicationController def readBoardAndUser response = {status:true} boards = Board.all.order("created_at DESC") users = User.all.order("id") response[:boards] = boards response[:users] = users render :json=> response
end

def insertComment
response = {status:true}

c = Comment.new({board_id: params[:board_id], user_id: params[:user_id], comment: params[:comment]})
c.save()

render :json=> response
end

def readComments
response = {status:true}
response[“X-CSRF-Token”] = form_authenticity_token

recs = Comment.eager_load(:user).where(“board_id = ?”, params[:board_id])
.order(“comments.created_at DESC”).as_json(include: :user)
response[“rows”] = recs

render :json=> response
end
end

[/bash]

routes.rbの編集

rnative_rails/config/routes.rb
[bash]
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get ‘board/readBoardAndUser’
post ‘board/insertComment’
get ‘board/readComments/:board_id’ => ‘board#readComments’

end

[/bash]

APIの動作確認

サーバーを起動して、ブラウザーにAPIのURLを入力
[bash]
$ rails s
[/bash]

http://localhost:3000/board/readBoardAndUser

下図のようにJSONが戻ってきてたら成功。
rn-34
これでバックエンドの処理は完成です。

React Nativeでクライアントサイドを実装する

プロジェクトの作成

[bash]
$ cd
$ cd workspace/reactnative_rails_board/
$ react-native init rnative
[/bash]

reduxをインストール

[bash]
$ cd rnative
$ npm install –save redux react-redux

[/bash]

Android Studioから ADV Manager起動

メニューより Tools >> Android >> AVD Manager

[bash]
$ /opt/android-studio/bin/studio.sh
[/bash]

AVD Managerより仮想デバイスを起動すると、以下のような画面が表示されます。
rn-35

React Nativeのデフォルトトップページを表示

[bash]
$ react-native start > /dev/null 2>&1 &
$ react-native run-android
[/bash]

以下のような画面が出れば成功です。
rn-36

Reduxの標準的なフォルダを作成

Reduxのお作法に従い、標準的なフォルダを作成します。

[bash]
$ mkdir actions constants containers components reducers

[/bash]

エントリーポイント調整、App.js作成

アプリケーションのエントリーポイントである index.android.jsを調整し、
アプリケーションのトップレベルの階層である App.jsを作成します。

rnative/index.android.js
[bash]
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/

import React, { Component } from ‘react’;
import {
AppRegistry,
StyleSheet,
Text,
View
} from ‘react-native’;
import App from “./components/App”;

export default class rnative extends Component {
render() {
return (



);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: ‘center’,
alignItems: ‘center’,
backgroundColor: ‘#F5FCFF’,
},
});

AppRegistry.registerComponent(‘rnative’, () => rnative);

[/bash]

rnative/components/App.js
[bash]
import React, { Component } from ‘react’;
import {
AppRegistry,
StyleSheet,
Text,
View,
} from ‘react-native’;

export default class App extends Component {
constructor(props){
super(props);
}
componentDidMount() {
}

render() {
return (


React Native! and Rails5.0!!


);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: ‘center’,
alignItems: ‘center’,
backgroundColor: ‘#F5FCFF’,
},
welcome: {
flex: 1,
fontSize: 20,
textAlign: ‘center’,
margin: 10,
},
});

[/bash]

動作確認

[bash]
$ react-native run-android
[/bash]

以下のように表示されればOKです。
rn-37

コンポーネント群作成

既に考えたパーツ構成に従い、コンポーネント群を作っていきましょう。

rnative/components/BoardList.js

[bash]
import React from “react”;
import {
StyleSheet,
Text,
View,
ListView,
Button
} from ‘react-native’;

const BoardList = () => {

return (


This is BoardList


);
}

export default BoardList;

[/bash]

rnative/components/CommentAdd.js
[bash]
import React from “react”;
import {
StyleSheet,
Text,
TextInput,
View,
ListView,
Button,
Picker
} from ‘react-native’;

const CommentAdd = () => {

return (


This is CommentAdd


)
}

const styles = StyleSheet.create({
row:{
flex: 1,
flexDirection: “row”
},
comment: {
width: 400
},
picker: {
flex: 3,
},
btn: {
flex:2
},
});

export default CommentAdd;

[/bash]

rnative/components/CommentList.js
[bash]
import React from “react”;
import {
StyleSheet,
Text,
View,
ListView,
Button
} from ‘react-native’;

const CommentList = () => {

return (


This is CommentList


);
}

export default CommentList;

[/bash]

ラッパークラス群(container)作成

Reduxでは、イベントやプロパティを割り当てたいコンポーネントの一層上に
ラッパークラス(container)をかぶせてやる必要があります。
コンポーネントのクラスの前に「C」をつけて、クラスを作りましょう。

rnative/containers/CBoardList.js
[bash]
import {connect} from “react-redux”;
import BoardList from “../components/BoardList”;

const mapStateToProps = (state, ownProps) => {
return {
}
}

const mapDispatchToProps = (dispatch) => {
return {
}
}
const CBoardList = connect(mapStateToProps, mapDispatchToProps)(BoardList);

export default CBoardList;

[/bash]

rnative/containers/CCommentAdd.js
[bash]
import {connect} from “react-redux”;
import CommentAdd from “../components/CommentAdd”;

const mapStateToProps = (state, ownProps) => {
return {
}
}

const mapDispatchToProps = (dispatch) => {
return {
}
}

const CCommentAdd = connect(mapStateToProps, mapDispatchToProps)(CommentAdd);

export default CCommentAdd;

[/bash]

rnative/containers/CCommentList.js
[bash]
import React from “react”;
import {connect} from “react-redux”;
import CommentList from “../components/CommentList”;

const mapStateToProps = (state) => {
return {
}
}

const CCommentList = connect(mapStateToProps, null)(CommentList);

export default CCommentList;

[/bash]

Reducerの作成

既に考えてあるステートを実装するReducerを作成します。
最初は難しいかもしれませんが、こんなもんだと思って慣れてください。

rnative/reducers/root.js
[bash]
import {combineReducers} from “redux”;
import sel_board from “./sel_board”;
import comments from “./comments”;
import csrf_token from “./csrf_token”;
import sel_user from “./sel_user”;

const rootReducer = combineReducers({
sel_board: sel_board,
comments: comments,
csrf_token: csrf_token,
sel_user: sel_user
});

export default rootReducer;

[/bash]

rnative/reducers/comments.js
[bash]
const comments = (state=[], action) => {
switch (action.type) {
case “COMMENTS_READ”:
return action.comments;
default:
return state;
}
};

export default comments;

[/bash]

rnative/reducers/csrf_token.js
[bash]
const csrf_token = (state=””, action) => {
switch (action.type) {
case “TOKEN_CHANGE”:
return action.token;
default:
return state;
}
}

export default csrf_token;

[/bash]

rnative/reducers/sel_board.js
[bash]
const sel_board = (state=-1, action) => {
switch (action.type) {
case “SELECT_BOARD”:
return action.id;
default:
return state;
}
};

export default sel_board;

[/bash]

rnative/reducers/sel_user.js
[bash]
const sel_user = (state=-1, action) => {
switch (action.type) {
case “SELECT_USER”:
return action.id;
default:
return state;
}
};

export default sel_user;

[/bash]

エントリーポイント、アプリケーションのトップ階層(App.js)の調整

createStoreで作成したストアを Providerのプロパティに渡し、Providerの子供に
App を設定します。

rnative/index.android.js
[bash]
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/

import React, { Component } from ‘react’;
import {
AppRegistry,
StyleSheet,
Text,
View
} from ‘react-native’;
import {Provider} from “react-redux”;
import {createStore} from “redux”;
import App from “./components/App”;
import rootReducer from “./reducers/root”;

export default class rnative extends Component {
constructor(props){
super(props);
}

render() {
let store = createStore(rootReducer);

return (



);
}

}

AppRegistry.registerComponent(‘rnative’, () => rnative);

[/bash]

アプリケーションのコンポーネントの骨格を作成します。
実際のコンポーネントではなくラッパークラス(container)でレイアウトを作ります。

rnative/components/App.js
[bash]
import React, { Component } from ‘react’;
import {
AppRegistry,
StyleSheet,
Text,
View,
} from ‘react-native’;
import CBoardList from “../containers/CBoardList”;
import CCommentList from “../containers/CCommentList”;
import CCommentAdd from “../containers/CCommentAdd”;

export default class App extends Component {
constructor(props){
super(props);
}
componentDidMount() {
}

render() {
return (


React Native! and Rails5.0!!





);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: ‘center’,
alignItems: ‘center’,
backgroundColor: ‘#F5FCFF’,
},
welcome: {
flex: 1,
fontSize: 20,
textAlign: ‘center’,
margin: 10,
},
});

[/bash]

動作確認

ここまでのところで動作確認します。
以下のような画面が出ればOKです。

[bash]
$ react-native run-android

[/bash]
rn-38

掲示板一覧を読み込み、表示する

さて、いよいよ、サーバーのAPIにアクセスして、データを読み込み、表示してみましょう。

その前に準備として、ActionCreatorの作成と、定数ファイルを作っておきましょう。

既に考えてある、イベントから、ActionCreatorを作ります。
これも慣れてください。

rnative/actions/index.js
[bash]
export const select_board = (id) =>{
return {
type: “SELECT_BOARD”,
id: id
};
}

export const comments_read = (comments) =>{
return {
type: “COMMENTS_READ”,
comments: comments
};
}

export const token_change = (token) => {
return {
type: “TOKEN_CHANGE”,
token: token
}
}

export const select_user = (id) =>{
return {
type: “SELECT_USER”,
id: id
};
}

[/bash]

アプリで使う定数群を扱うファイルです。
今回はAPIサーバーが起動している開発PCのIPアドレスをセットしておきます。
ここは、ご自身の開発マシンのIPアドレスをセットしてください。

rnative/constants/index.js
[bash]
export const HOST_ADDR=’192.168.11.6:3000′;

[/bash]

アプリの起動時にAPIサーバーにアクセスし、掲示板一覧・ユーザー一覧を取得(readInit)し、
CBoardListとCCommentAdd のプロパティにセット。

rnative/components/App.js
[bash]
import React, { Component } from ‘react’;
import {
AppRegistry,
StyleSheet,
Text,
View,
ListView
} from ‘react-native’;
import {HOST_ADDR} from “../constants/index”;
import CBoardList from “../containers/CBoardList”;
import CCommentList from “../containers/CCommentList”;
import CCommentAdd from “../containers/CCommentAdd”;

export default class App extends Component {
constructor(props){
super(props);

let dsBoard = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});

this.state = {dataSourceBoard: dsBoard, users: []};
}
componentDidMount() {
this.readInit();
}

render() {
return (


React Native! and Rails5.0!!





);
}

readInit() {
let dsBoard = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});

fetch(‘http://’ + HOST_ADDR + ‘/board/readBoardAndUser’)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSourceBoard: dsBoard.cloneWithRows(responseJson.boards),
users: responseJson.users
});
})
.catch((error) => {
console.error(error);
});
}

}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: ‘center’,
alignItems: ‘center’,
backgroundColor: ‘#F5FCFF’,
},
welcome: {
flex: 1,
fontSize: 20,
textAlign: ‘center’,
margin: 10,
},
});

[/bash]

rnative/containers/CBoardList.js
[bash]
import {connect} from “react-redux”;
import {select_board} from “../actions/index”;
import {HOST_ADDR} from “../constants/index”;
import BoardList from “../components/BoardList”;
import {comments_read, token_change} from “../actions/index”;

const mapStateToProps = (state, ownProps) => {
return {
dsBoard: ownProps.dsBoard,
sel_board: state.sel_board
}
}

const mapDispatchToProps = (dispatch) => {
return {
onBoardSelect: (id) => {
dispatch(select_board(id));
}
}
}

const CBoardList = connect(mapStateToProps, mapDispatchToProps)(BoardList);

export default CBoardList;

[/bash]

読み込まれたデータをループで展開し、1行を表す BoardLineをn個作る。

rnative/components/BoardList.js
[bash]
import React from “react”;
import {
StyleSheet,
Text,
View,
ListView,
Button
} from ‘react-native’;
import BoardLine from “./BoardLine”

const BoardList = ({dsBoard, sel_board, onBoardSelect}) => {

return (

{
let act = rowData.id == sel_board ? true : false;
return (
onBoardSelect(id)}
/>
)
}}
/>

);
}

export default BoardList;

[/bash]

掲示板の1行を意味するBoardLineクラスの作成

[bash]
import React from “react”;
import {
StyleSheet,
Text,
View,
Button
} from ‘react-native’;

const BoardLine = ({active, rowData, onPress}) => {
let styleTitle = [styles.title];
if (active){
styleTitle = [styles.title, styles.active];
}
return (

{rowData.title}

About the author:

Related Posts

Leave a comment

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

Back to Top