この記事の目的
Vue経験者でReactに興味ある人が"やるorやらない"を決めるキッカケになればいいかなと思います。
自己紹介
情報専門学生3年のkazzです。
学校とはまた別で、Web開発のデザイン以外を手広く触っています。最近はもっぱらSPAつくってます(バックNodejs,フロントReact,インフラAWS/EC2)。
ちなみに自分は、ReactもVueも個人制作やハッカソンで使う程度で実務では使ったことがないですし、そこまで精通しているわけでもないので、本記事は「そういうもんなんだな〜」程度で見てくれるとありがたいです。
Reactに移行してみて
移行した経緯
一番は知的好奇心です。
正直、当時のVueの選択理由も学習コストの低さと情報の多さくらいで「まあVueでいいか」みたいな感じだったので、Vueを書き始めて3ヶ月ほどでやはりReactやAngulerに興味が湧いてきてしまい、JavaScriptもそこそこ書けるようになってきたのもあって、Reactに移行することにしました。
Reactを選んだ理由
Angulerは大規模開発向きな分ニーズが偏っているそうで、現在の案件数も一番多く将来性もありそうなReactを選択しました。
それに、Angulerは小中規模のアプリを開発するにしてはオーバーヘッドが大きく向いていないそうですし、自分的には違うかなと感じました。
VueからReactに移行して良かったこと、悪かったこと
カスタムフックなどで処理を外部化できたり、あらゆる面で拡張性の高さを感じました。一方で、理解が曖昧だとででたらめなコードを書いてしまいそうとだなとも感じました。
参考: 条件付きレンダー
実際Vueのときと比べ、Reactだから出来たとか出来ないだとかは特にありませんし、どちらも日本語ドキュメントが用意されていますし(※19年12月時点でReactは一部和訳されていない部分があるが、そんなに支障はなかった)、ライブラリも豊富に存在します。
難易度、学習コスト
現段階では、どちらもさほど変わらないかなという印象です。
ただ、VueのSFCのような直感的な分かりやすさはなく、少し慣れが必要かなと感じました。
あと、Vue以上にES6の理解は必要です。公式のチュートリアルにも「ES6 という JavaScript の最近のバージョンからいくつかの機能を使用していることにも注意してください」と書かれています。
最低でもconst,letや分割代入、スプレッド演算子、アロー関数くらいはやっておくとスムーズに学習できると思います。
実際に触ってみよう
環境構築(Vue環境有前提)
Nodejsの環境は出来上がっていると思うので、さくっとプロジェクトを作成しましょう。
まず、npmを使わずnpxコマンドからcreate-react-appを実行し、プロジェクトの雛形を作成します。
npx create-react-app sample-app
# TypeScriptを導入する場合は↓で実行
# npx create-react-app sample-app --typescript
とりあえずnpm run start
でReactアプリケーションを起動してみましょう。
さらに、ディレクトリを少し整頓して、src/App.jsを最小構成にしてみましょう。
Vueとの比較
せっかくなのでReactの一部機能をVueと比較しながら紹介します。
Template→JSX
ReactではJSXという記法を使いHTMLを表現します。Vueでいう単一ファイルコンポーネントのtemplateみたいな感じです。
JSX構文を使えばHTMLをJavaScriptにそのまま書くことができ、更には変数に代入し利用することも可能です。View内で変数を使い場合は{}
で囲めばその中は式として判定されます。
Vueの場合
<template>
<div class="App">
Hello, OthloTech!
</div>
</template>
<script>
export default { };
</script>
<style scoped>
.App {
margin: 200px;
}
</style>
Reactの場合
import React from 'react';
import "./App.css"; // <- CSSファイル適用
const App = () => {
return (
<div className="App">
Hello, OthloTech!
</div>
);
}
export default App;
.App {
margin: 200px;
}
State
VueでいうdataがReactのStateにあたります。コンポーネント内の情報で保持する変数です。
Vueはdataの中身を直接再代入すればViewにも反映されますが、Reactはそうはいきません。State定義時にあわせてセッター関数も定義し、そのセッター経由でデータの変更を行います。
次の例はよくあるカウントアップアプリを実装しています。
Vueの場合
<template>
<div>
<div>{{count}}</div>
<button @click="count += 1">PLUS</button>
</div>
</template>
<script>
export default {
data: () => ({
count: 0
})
};
</script>
Reactの場合
import React from 'react';
const App = () => {
// value setter 初期値
// ↓ ↓ ↓
const [count, setCount] = React.useState(0);
return (
<div>
<div>{count}</div>
<button onClick={() => { setCount(count + 1) }}>PLUS</button>
</div>
);
}
export default App;
Props
おなじみpropsです。
Vueの場合
<template>
<div>
<h2>{{title}}</h2>
<div>{{content}}</div>
</div>
</template>
<script>
export default {
props: {
title: String,
content: String
}
};
</script>
<template>
<div>
<SampleComponent title="Title!1" content="Content!1" />
<SampleComponent title="Title!2" content="Content!2" />
<SampleComponent title="Title!3" content="Content!3" />
</div>
</template>
<script>
import SampleComponent from "./components/SampleComponent.vue";
export default {
data: () => ({
count: 0
}),
components: {
SampleComponent
}
};
</script>
Reactの場合
import React from 'react';
const SampleComponent = (props) => {
return (
<div>
<h2>{props.title}</h2>
<div>{props.content}</div>
</div>
);
}
export default SampleComponent;
import React from 'react';
import SampleComponent from './components/SampleComponent';
const App = () => {
return (
<div>
<SampleComponent title="Title!1" content="Content!1" />
<SampleComponent title="Title!2" content="Content!2" />
<SampleComponent title="Title!3" content="Content!3" />
</div>
);
}
export default App;
API通信(Axios)
こちらはVueは省略します。
useEffectはコンポーネントのレンダリング後に走らせたい処理をコールバックで渡します。その中でAxiosを使ってpokeAPIからデータを取得し、そのレスポンスをstateのセッター経由でviewに反映させます。
以下の例ではpokeAPIからポケモンの図鑑No1〜10のデータを取って、一覧表示させています。
実行結果
Reactコード
import React from 'react';
import Axios from "axios";
const App = () => {
const [pokemons, setPokemons] = React.useState(null);
const [isApiConFailed, setIsApiConFailed] = React.useState(false);
React.useEffect(() => {
Axios.get("https://pokeapi.co/api/v2/pokemon?offset=0&limit=10").then(response => {
setIsApiConFailed(false);
setPokemons(response.data.results);
}).catch(error => {
setIsApiConFailed(true);
});
}, []);
const ApiResult = (
pokemons !== null && (
pokemons.map((pokemon, index) => (
<div key={index}>
<h2>{pokemon.name}</h2>
<div>
<a href={pokemon.url}>このポケモンの詳細</a>
</div>
</div>
))
)
);
return (
<div>
{ApiResult}
{isApiConFailed && <div>API通信エラー</div>}
</div>
);
}
export default App;
学習方法
1.ハローワールド
2.UdemyのReactコースや公式ドキュメントを参考に色んな機能を試す
3.Vueで作りかけだったものをReactで書き直す
React公式ドキュメント:
https://ja.reactjs.org/docs/getting-started.html