- 投稿日:2020-11-14T21:40:53+09:00
react-image-cropで画像のトリミング機能を実装する方法
react-image-cropを用いたトリミング機能を追加するところで躓いたので、自分へのメモとして書きました。
state
index.tsxconst [src, setSrc] = useState<any>(null); const [crop, setCrop] = useState<Crop>({ unit: "%", x: 0, y: 0, width: 50, height: 50, aspect: 1 }); const [imageRef, setImageRef] = useState<HTMLImageElement | null>(null);画像を読み込む関数
index.tsxconst onSelectFile = (event: React.ChangeEvent<HTMLInputElement>) => { if (event.target.files !== null) { const reader = new FileReader(); reader.addEventListener("load", () => setSrc(reader.result); ); reader.readAsDataURL(event.target.files[0]); } }; const onImageLoaded = (image: HTMLImageElement) => setImageRef(image); };画像をトリミングする関数
index.tsxconst onCropChange = (crop: Crop) => { setCrop(crop); }; const onCropComplete = (crop: any) => { if(imageRef && crop.width && crop.height){ const canvas = document.createElement("canvas") const scaleX = imageRef.naturalWidth / imageRef.width; const scaleY = imageRef.naturalHeight / imageRef.height; canvas.width = crop.width canvas.height = crop.height const ctx = canvas.getContext("2d") if (ctx !== null) { ctx.drawImage( imageRef, crop.x * scaleX, crop.y * scaleY, crop.width * scaleX, crop.height * scaleY, 0, 0, crop.width, crop.height ) } } };コンポーネント
index.tsximport React, {useState} from "react"; import ReactCrop, {Crop} from "react-image-crop"; import "react-image-crop/dist/ReactCrop.css"; export const CropModal: React.FC<Props> = props => { ... return ( <div> <input type="file" accept="image/*" onChange={onSelectFile} /> {src && ( <ReactCrop src={src} crop={crop} ruleOfThirds onImageLoaded={onImageLoaded} onComplete={onCropComplete} onChange={onCropChange} /> )} <div/> ) }今回トリミングした画像データをサーバーにアップロードするには、canvasのデータをBlobデータに変換し、axiosを用いてDataFormとして送る。
canvasの画像データをblobに変換し、axiosでpost.する方法
参考にした記事
- 投稿日:2020-11-14T20:32:04+09:00
React × TypeScript 入門
はじめに
30代未経験からエンジニアを目指して勉強中のYNと申します。
JavaScriptでReactが書ける人向けの、React × TypeScript入門記事です。新しいReactプロジェクトつくる
npx create-recact-app <your-pjt-name> --typescriptコードを書き始める前に
SnippetからReactコンポーネントのテンプレートを作る
まずはSnippetを作ると楽です。
VScodeであれば、Snippetを使って一瞬でコンポーネントのテンプレートを持って来れます。
cmd + shift + p>Preference:Configure User Snippets>typescriptreactでスニペットの設定ができます。typescriptreact.jsonを下記のように変更します。typescriptreact.json{ "Typescript React Function Component": { "prefix": "rh", "body": [ "import React from 'react'", "", "interface ${TM_FILENAME_BASE}Props {", "$1", "}", "", "export const $TM_FILENAME_BASE: React.FC<${TM_FILENAME_BASE}Props> = ({$2}) => {", "\t\treturn ($3);", "}" ], "description": "Typescript React Function Component" } }オートサジェストを有効にする
TypeScriptを使うメリットの一つに、型指定によるオートサジェストにあります。 試しにpropsの場所で
Ctrl+Spaceを押すと、指定可能なpropsの一覧が表示されます。
VScodeであれば、デフォルトでCtrl+Spaceで有効になっているはずです。
もし作動しなければ、(Macの場合)システム環境設定>キーボード>ショートカットでCtrl+Spaceの既存ショートカットを無効化しましょう。Reactコンポーネントの基本
Function Component
interfaceで型を定義し、
React.FCにgenericsとして渡します。TextField.tsximport React from "react"; interface Props { text: string; ok?: boolean; i?: number; } export const TextField: React.FC<Props> = ({text ="hello", i=1, ok=true }) => { return ( ... ); };onClick
マウスホバーすれば、定義すべき型がわかります。
OnClick.tsximport React from 'react'; interface OnclickProps { onClick?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void; // divタグのonClickにカーソルを合わせると、この型を指定すればいいことがわかる text?: string; } const Onclick: React.FC<OnclickProps> = ({ onClick, text }) => { return <div onClick={onClick}>{text}</div>; }; export const Click: React.FC<OnclickProps> = () => { const logText = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => console.log(e.target); return <Onclick onClick={logText} text={'hello!!'} />; };Hooks
useState
Hooksもgenericsで型を定義します。
Counter.tsximport React, { useState } from 'react'; interface CounterProps { initialCount: number; } export const Counter: React.FC<CounterProps> = ({ initialCount }) => { const [count, setCount] = useState<number>(initialCount); // countの型をgenericsで指定 return ( <> <button onClick={() => setCount(count + 1)}>+</button> <div>{count}</div> </> ); };useReducer
ActionやStateもtypeやinterfaceを使って型を定義します。
Reducer.tsximport React, { useReducer } from "react"; type Actions = | { type: "add"; text: string } | { type: "remove"; idx: number; }; interface Todo { text: string; complete: boolean; } type State = Todo[]; const TodoReducer = (state: State, action: Actions) => { switch (action.type) { case "add": return [...state, { text: action.text, complete: false }]; case "remove": return state.filter((_, i) => action.idx !== i); default: return state; } }; export const ReducerExample: React.FC = () => { const [todos, dispatch] = useReducer(TodoReducer, []); return ( <div> {JSON.stringify(todos)} <button onClick={() => { dispatch({ type: "add", text: "..." }); }} > + </button> </div> ); };参考
- 投稿日:2020-11-14T19:00:03+09:00
React やってみたら超簡単だった話(2020年11月版)
React / Vue.js / Angular / jQuery
Angularjsが出た時に、jQueryでもういいじゃん新しい言語覚えるのめんどくせーよと思いながらやってみたら、超便利で新しい言語ちゃんと覚えないとダメだなと改心したのが遠い分昔。
その後、Angularの頻繁なバージョンアップに嫌気がさしVue.jsを使ってみたら、Angularより随分整理されてて簡単でびっくりしたのが少し昔。
Vuetify とセットで利用するとほとんどコードを書かずにやりたいことができるし、typescript を使うと記述もシンプルで安全だし、もうこれで新しい言語覚えなくてもいいかと油断したのが少し前。とは言え、Reactも触っておいた方がいいかなと触ったら、他のフレームワークとは概念が違い戸惑ったけれども超簡単でびっくりしたのが今日。
触ってみたいけど難しそうだなと思ってる方は是非触ってみてください。
特に便利と思ったところ
jsx/tsx
js/ts に html を直接埋められる。
以下のコードは等価。
createElement.jsconst header = React.createElement("header", null, React.createElement("h1", null, "Hello") );createElement.jsxconst header = <header> <h1>Hello</h1> </header>
React.createElementの様な書き方しかできないならVue.js圧勝かなと思ったけれども、そんなことはなかった。Flutterもこの辺融通効くようにならないかな…。ベタのhtmlに近い形で記述できるVue.jsの方がデザイナとの協業に強いと思っていたのだけど、Storybookを併用して開発すれば問題ないようにも思えた。
Function Component
状態を持たないコンポーネントは class ではなく、function で定義できる。
Flutter の、StatefulWidget / StatelessWidget をすごくシンプルにした感じ。以下のコードは等価。
class-component.jsxclass Square extends React.Component { render() { return ( <button className="square" onClick={() => this.props.onClick()} > {this.props.value} </button> ); } }function-component.jsxfunction Square(props) { return ( <button className="square" onClick={props.onClick}> {props.value} </button> ); }記述がシンプルなだけでなく、このコンポーネントは状態を持たないことが読み手に一瞬で伝わるのが素晴らしいと思った。
チュートリアル
React公式のチュートリアルが、ステップバイステップでサンプルコードを修正していくものとなっており、Reactの素晴らしさを簡単に理解できる作りとなっていた。
準備
チュートリアルのソースコードは code pen にあるため、ローカルの開発環境作成は必須ではない。
ローカルの開発環境を作成する場合、node と create-react-app のインストールを行う。choco install nodist nodist + 10.23.0 nodist 10.23.0 npm i -g create-react-app2020/11/14時点では、node 8, 10, 12 で動作すると記載があったが、8.17.0, 12.19.0 では動作しなかった。
プロジェクト作成と実行
# js版作成 npx create-react-app my-app # ts版作成 npx create-react-app my-app --typescript # 実行 yarn start以後は、src以下のファイルを全部消して、チュートリアルの指示通りファイルを作成し、一つずつ修正をしていけば完了します。
コンポーネント単位でファイルを分けるなども簡単にできました。
おわりに
とにかく超簡単でした。
vue-cli もそうであるが、webpack.config を手で書かなくて良くなったので誰でも気軽に始められるのでぜひお試しください。以下の記事もあわせて読んでおくとよいと思います。
- 投稿日:2020-11-14T18:45:51+09:00
Firestoreでidのわからないdocumentを取得したいときはどうすればいいのか
firestoreはフロントエンドエンジニアが個人でwebサービスを作る際に、わざわざデータベースを一から作っていく必要がなく、数行のコードでデータを保存したり、取得したりととても便利なサービスです。
ただ、使いはじめの頃、必ずと言っていいほど
idのわからない(または自動で付与されたidの)documentをどうやって取得するのかという壁が立ちはだかります。公式ドキュメントでは
firebase.firestore.collection("cities").doc("SF").get()で取得できると書いてあるけど、この例でのSFと言うidがそれ以外、もしくは複数のドキュメントをgetしたい場合にはどうすればいいのかと言う話です。結論:docを使わなくてもdocumentの取得は可能
公式リファレンスをみていただければわかると思いますが、データの取得に使う
get()メソッドは返り値としてQuerySnapshotを返します。この
QuerySnapshotはdocumentのidを持っていますし、このsnapshotからdocumentを取り出すことが可能です。documentの取り出し方の一例を紹介
ここでは僕のパターン(React)を紹介します。
Example.jsxconst getPosts = () => { //空の配列postsを準備します let posts = [] //firebaseお決まりのメソッドでコレクションからデータを取ってきます //ここでのポイントは「doc()がいらないこと」です db.collection('posts').get() //getしたデータに対し、 .then(snapshot => { //docsプロパティ(※)を指定しforEachで各データを取り出します。 snapshot.docs.forEach(doc => { const data = doc.data() //準備しておいた配列に取り出したデータをpushします posts.push({ authorName: data.authorName, content: data.content, createdAt: data.createdAt, title: data.title, id: doc.id }) }) //ここはhooksなので気にしなくてOK setCurrentPost(posts) }) }※マークをつけたdocsプロパティは、get()メソッドの返り値QuerySnapshotが持つ、プロパティで指定したcollectionのデータを配列として持っています。複雑ですね...w
この辺の返り値や持っているプロパティなどに関しては英語しかありませんがfirebaseの公式リファレンスに細かく説明が載っています。番外編:documentのidを自動的に付与する方法について
ここも少し迷ったところなので、一応紹介します。
今度は逆にデータを保存する方法についてなのですが、firestoreでは自動idが推奨されていますが、この自動のdocument idをどのようにつけるのかというと、
add()を使います。Form.jsxdb.collection('posts').add({ title: title, content: content, authorName: authorName })このように
addを使えばデータを保存する時に自動idを生成してくれます。ちなみにデータを追加する時に
set()と言うメソッドも使いますが、これはdocumentのidを指定する必要がありますし、idを自動で生成してくれません。「じゃあ使わなくていいじゃん」と思うかもしれませんが、これはこれで、データの編集の際に
{ merge: true }と引数に指定することで、値が変わっているところだけ更新するので、無駄な書き込みが無いなどのいいところもあります。このようにしてデータの追加の際はaddにすれば自動でidが生成されるのです。
firebaseは公式ドキュメントを読めば結構理解できる
firebaseはかなり公式のドキュメントが充実しています。
今回のようなわからないメソッドなどがあった場合はリファレンスを見れば、大切なところが全て書いてありますし、導入部分の簡単な使い方については日本語のドキュメントがあります。
ですので、
firebase関連でわからないことがあったら、とりあえず公式ドキュメントをみましょうと言うお話でした?参考
- 投稿日:2020-11-14T16:36:10+09:00
Reactを学ぶIX〜importとexport〜
■ はじめに
タイトルについて記事にしました。
この記事で得る内容は以下の通りです。・ Reactの基礎知識が増える
・ importとexportの理解とモジュールについて■ モジュール化とは
→ 大きなものをいくつかにモジュール毎に分割して管理する
・ 他のJavaScript以外の言語では昔からある概念
・ JavaScriptではES2015(ES6)から採用
・ 基本的に1ファイルに1モジュール
・ モジュールを作ったら、任意の場所でモジュールを読み込んで使用できる
■ モジュール化の効果
Reactは、このモジュールの概念を強く意識して作られています。
Reactのコンポーネントを作ったらそれが1個のモジュールになっており、それを必要な所で読み込んだり・・・
コンポーネントを分ける事で管理をしやすくしたり・・・
同じUIの所であれば、それを何度も何度も使い回して使ったり・・・
Reactとモジュールの関係はお互いに強く結びついていると言えます■ モジュールを作る
モジュールを作る時は、exportを使います。exportは名前付きexportと名前なしexportの2種類あります
・ 名前付きexport
→ 1つのモジュールから複数の関数をexportできるが、クラスはexportできない
src/index.js// 関数を用いる export function foo() { return (<h1>Foooo</h1>) } // 或いはアロー関数を使う export const Bar = () => { return (<h1>Baaaar</h1>) }exportした
fooという関数を別の所で使ったり、Barという関数をimportして別の所で使うことができます・ 名前なし(default)export
→ 1ファイル(1モジュール)1つだけexportし、ES6で推奨されているexport方法です
src/Foo.jsexport default function Foo() { return (<h1>Fooooo</h1>) }アロー関数の場合は、
export default const hogeの様な書き方はできませんので
先にアロー関数で宣言してからexportしますsrc/Bar.jsconst Bar = () => { return (<h1>Baaaar</h1>) } export default Barそして、名前なしexportであれば、クラスもexportすることができます
src/Hoge.js// Fugaというクラスを継承したHogeというクラスを作ってexportする export default class Hoge extends Fuga { render() { return (<h1>Hoge</h1>) } }■ import
importする方法は3つあり、モジュール全体をimport・モジュールの一部をimport・別名でimportする方法があります
・ モジュール全体のimport
→ 名前なし(default)exportしたモジュールをimportする時に使う
src/Blog.jsimport React from `react`; import Article from "./Article"; // npmで管理しているreactパッケージの中のReactというモジュールをimportしている // ArticleファイルからArticleというモジュールをipmortしているsrc/Article.jsconst Article = (props) => { return (<div>Articleです!</div>) }; export default Article・ 関数ごとのimport
→ 名前付きexportされたモジュールをimportする時に使う
src/Hoge.jsimport { Foo, Bar } from "./FooBar"; // {}内にimportした関数名を記述 // FooBarというファイルから、FooとBarをimportするsrc/FooBar.jsexport function Foo() { return (<h1>Foooo</h1>) } export const Bar = () => { return (<h1>Baaaar</h1>) } // 名前付きexportなので、1ファイルで2つのモジュールがexportされている・ 別名import
→ importする時は、export元の名前を使うのが一般的だが、別名(エイリアス)をつけてimportできる
・ モジュール全体なら*as name
・ モジュールの一部なら{ A as B }src/Blog.jsimport React from 'react'; import * as AnotherName from './Article' // ① AnotherNameという名前でArticleのモジュールをimportする import { Foo as MyFoo } from './FooBar' // ② FooBarファイルからFooという関数をMyFooという名前でimportする■ 例
① 以前のプロジェクトを流用します。まず、src内に新規ディレクトリを作ります
② 作成した新規ディレクトリの中に、
FooBar.jsxというファイルを作成して、名前付き関数を2つ記述しますFooBar.jsximport React from 'react' export function Foo() { return(<h2>Foooo</h2>) } export const Bar = () => { return(<h2>Baaar</h2>) } // FooBar.jsxからは、2つ関数をexportしていることになる③ 作成した新規ディレクトリの中に、
Hoge.jsxというファイルを作成して、クラスコンポーネントをexportしますHoge.jsximport React from 'react' export default class Hoge extends React.Component { render() { return(<h2>Hogeeee</h2>) } }④
Blog.jsxで先程作ったモジュールをimportしていきますBlog.jsximport { Foo, Bar } from './components/FooBar' // 名前付きexport // 参照先が相対パス(現在変更しているファイル目線)になるので注意⑤ 名前なしクラスの
Hoge.jsxもimportしていきますBlog.jsximport Hoge from './components/Hoge'⑥ これらのコンポーネントを並べて実際に使ってみます
Blog.jsxrender () { return( <> <Article title={"Reactの使い方"} isPublished={this.state.isPublished} toggle={() => this.togglePublished()} count={this.state.count} /> <Foo /> <Bar /> <Hoge /> </> ); }Foo関数とBar関数、hogeクラスを表示することができました
⑦ 別名importで
FooBarを読み込むには、以下の書き方をしますBlog.jsximport * as FooBar from './components/FooBar' // FooBarとい名前でファイル全体をimportする // 中略 render () { return( <> <Article title={"Reactの使い方"} isPublished={this.state.isPublished} toggle={() => this.togglePublished()} count={this.state.count} /> <FooBar.Foo /> <FooBar.Bar /> <Hoge /> </> ); } // FooBarの中のFoo関数とBar関数を読み込む
- 投稿日:2020-11-14T16:13:09+09:00
「This is the wrong package! Please install eslint-plugin-jsx-a11y」のエラー
エラー内容
りあクト!の【II.React基礎編】で
$ yarn add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin \ eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-import \ eslint-plugin-jsx-ally eslint-config-airbnbと入力したところ
error /.../hello-world/node_modules/eslint-plugin-jsx-ally: Command failed. Exit code: 1 Command: node ./postinstall.js Arguments: Directory: /.../hello-world/node_modules/eslint-plugin-jsx-ally Output: /.../hello-world/node_modules/eslint-plugin-jsx-ally/postinstall.js:1 throw new Error('This is the wrong package! Please install eslint-plugin-jsx-a11y')のエラーが出ました
結論
タイポでした!
「eslint-plugin-jsx-a11y」の「a11y」は英字のLの小文字ではなく数字の11でした!感想
恥ずかしいです。。。
他にも、りあクト!の【II.React基礎編】の少し前のページで
$ yarn eslint --initでエラーが出て、解決のためにいろいろ調べてなんとか解決したところで、次の会話で柴崎さんが「なおコマンドがエラーで終わっても、とりあえずは気にしなくてもいいから」とおっしゃられていました。
恥ずかしいです。。。
- 投稿日:2020-11-14T15:34:30+09:00
Next.js + MaterialUIでfontを指定する
手順
- 使用したいfontファイル(woff/otfなど)を
public/fonts配下に設置@font-faceを記載したcssファイルも同様にpublic/fonts配下に設置_document.tsxのheadタグにlinkタグ設置<link rel="stylesheet" href="fonts/fonts.css" />_app.tsx内でProviderに渡すthemeを作成(styles/theme.tsに作成)- 作成した
theme.tsを_app.tsxでimportする実際のコード
public/fonts/fonts.css@font-face { font-family: 'fontname'; font-weight: normal; font-style: normal; src: url('./fontname.woff'); }src/pages/_document.tsximport React from 'react' import NextDocument, { Head } from 'next/document' return ( // 略 <Head> <link rel="stylesheet" href="fonts/fonts.css" /> </Head> // 略 )src/styles/theme.tsimport { createMuiTheme } from '@material-ui/core' let theme = createMuiTheme({ typography: { fontSize: 16, fontFamily: ['fontname'].join(',') } }) export default themesrc/pages/_app.tsximport React, { useEffect } from 'react' import { ThemeProvider as MaterialUIThemeProvider, StylesProvider } from '@material-ui/styles' import theme from '../../styles/theme' const MyApp = ({ Component, pageProps }: any): JSX.Element => { return ( <StylesProvider> <MaterialUIThemeProvider theme={theme}> <CssBaseline /> <div>{pageProps.appData}</div> <Component {...pageProps} /> </MaterialUIThemeProvider> </StylesProvider> ) } export default MyApp
- 投稿日:2020-11-14T01:44:05+09:00
React入門 未経験から1週間でReactをマスターする #03. Class ComponentsとFunction Componentsの書き方
目次
1. Reactの新規プロジェクトの立ち上げ
2. コンポーネントのプロパティ(props)とステート(state)
3. Class Components と Function Components←今ここ
4. 条件分岐 (if) と繰り返し (loop) (準備中)
5. フォームと親子間のデータのやり取り (準備中)
6. コンポーネントのライフサイクル (準備中)
7. スタイル (準備中)
8. Higher-Order Component (準備中)
9. Portalを利用したモーダル (準備中)
10. refによるエレメントの取得 (準備中)
11. Contextを利用したテーマの変更 (準備中)今回の学習内容
今回は、
- Class Components , Function Components の書き方についての理解
- Class Componentsでのコンポーネントの書き方
をやっていきます。
YouTubeでの解説動画
YouTubeでも解説しています。
動画で確認したい方はこちらもどうぞ。
【YouTube動画】 未経験から1週間でをマスターするReact入門 #03. Class ComponetnsとFunction Componentsの書き方
この記事のソースコード
ソースコードはGitHubで公開しています。
https://github.com/yassun-youtube/ReactTutorial
Class Components
少しずつReactの書き方がわかってきたところで、
Class ComponentsとFunction Componentsの話をします。Reactでのコンポーネントの書き方に、
Class ComponentsとFunction Componentsがあります。
Function Componentsは、本入門で紹介してきた書き方で、functionを定義するとそれがコンポーネントになりました。
Class Componentsは、 JavaScript のクラスを記載することで、コンポーネントを定義する書き方です。今は
Function Componentsの書き方が使われることが多くなってきていると思いますが、Class Componentsの書き方もまだまだ使われているため、Class Componentsの書き方を学んでおく必要があります。今回は、
App.jsをClass Componentsで書き直してみます。ブランチの作成
本入門では、すべてのコードを
Class Componentsで記載したものを別ブランチで管理します。
class-componentsブランチを作成しましょう。git checkout -b class-componentsApp.js の Class Components 化
まず、一番単純なコンポーネントにしてみます。
src/App.js// 全体的に書き直し import React from 'react'; class App extends React.Component { render() { return ( <div>クラスコンポーネントにしてみました。</div> ) } } export default App;もともと
functionだったものが、classに変わっていることがわかると思います。
functionだったときは、そのreturnで<div>を返していましたが、Class Componentsでは
render関数の返り値が表示するものになります。画面表示を確認してみましょう。
このようになりました。
List.js の Class Components 化
List.jsも同じ様に変更します。src/List.jsimport React from 'react'; export class List extends React.Component { render() { const { title } = this.props; return ( <div> <h4>{ title }</h4> <div>リストです</div> </div> ) } }
Listコンポーネントでは、propsのtitleという値を利用していました。
Class Componentsでは、this.propsにpropsが入っています。
Function Componentsでは、下記のように関数の引数に入っていましたね。const List = ({ title }) => {}App.jsから List.js を呼び出す
src/App.jsimport React from 'react'; import { List } from "./List"; class App extends React.Component { render() { return ( <div> クラスコンポーネントにしてみました。 <List title="取り扱い言語一覧" /> // 追加 </div> ) } } export default App;これは以前行った変更と同じですね。
画面表示は下図のようになります。
Class Components での state の利用
App.jsでstateを利用するようにコードを修正してみます。App.jsimport React from 'react'; import { List } from "./List"; class App extends React.Component { constructor(props) { super(props); this.state = { description: 'クリック前の表示' } } changeDescription() { this.setState({ description: 'クリック後の表示です。' }) } render() { const { description } = this.state; return ( <div> { description } <List title="取り扱い言語一覧" /> <button onClick={() => this.changeDescription()}>ボタン</button> </div> ) } } export default App;同じことができるコードなのですが、
Function Componentsより少し長いですね。
画面にはボタンが表示されていて、クリックすると下記のように表示されます。コードの解説
Class Componentsでは、stateの初期値は constructor で定義します。constructor(props) { super(props); this.state = { description: 'クリック前の表示' } }ここですね。
constructorはpropsを引数にとり、それをsuper(props)で渡す必要があります。
その後、stateを初期化しています。
初期化のときは、this.state = {}と=を使います。次に
changeDescriptionを見ていくと、changeDescription() { this.setState({ description: 'クリック後の表示です。' }) }となっていて、
setStateという関数でstateを更新していることがわかります。
ここで注意して欲しいのが、これはthis.state =では動きません。Reactでは、ステートの更新を明示的に関数で呼び出してやる必要があります。
setStateを呼ばれると、Reactがコンポーネントの表示を更新する必要があるとわかるわけですね。最後に、
buttonに対してのonClickイベントを追加している部分を見ていきます。<button onClick={() => this.changeDescription()}>ボタン</button>ここでは、
onClickでchangeDescriptionメソッドを呼び出しています。ここで注意してほしいのが、
onClickでchangeDescription関数の参照だけを渡すとエラーになることです。<button onClick={this.changeDescription}>ボタン</button>このように記載を変えると、ボタンを押すとエラーになります。
参照だけ渡すと
thisの罠に捕まってしまうので、ちゃんとこのインスタンスが参照されるように意識しましょう。ちなみに、
bindでthisを固定してもちゃんと動きます。
こちらの書き方のほうが好きという方はこちらの書き方を利用しても良いです。<button onClick={this.changeDescription.bind(this)}>ボタン</button>今日やったこと
今日やったことをまとめます。
Class Components と Function Componentsの違い
一番単純なコンポーネント
class ClassComponent extends React.Component { render() { return ( <div>クラスです。</div> ) } }function FunctionComponent { return ( <div>ファンクションです</div> ) }プロパティの違い
Class Componentsでは、
this.propsFunction Components
function FuncCompo(props) {}ステートの違い
初期化
Class Components
constructor(props) { super(props); this.state = { test: initialValue }; }Function Components
const [test, setTest] = useState(initialValue);ステートの変更
Class Components
this.setState({ test: value })Function Components
setTest(value);おわりに
これで入門 その2と同様のコードを
Class Componentsの書き方で書くことができました。
今後の入門は、基本的にFunction Componentsの書き方で書いていきますが、Class Componentsでの書き方も解説していきます。













