夢のかけら

Goエンジニアの技術ブログ

【React】子コンポーネントから親コンポーネントへデータを渡す

f:id:lampler:20210519200542p:plain

子が好きなタイミングで親のメソッド実行する

Vueと同じように子コンポーネントの好きなタイミングで親コンポーネントに作成したカスタムイベントを発火させることができる。その時の引数としてデータを受け取る、という流れである。

注意点として、親コンポーネントではカスタムイベント={メソッド名}として関数への参照を渡す。 子から送られてきたデータは引数としてメソッド内で受け取ることができる。

// 親コンポーネント

handleMyEvent = (value) => {
  console.log(value) // 3
}

<Counter myEvent={this.handleMyEvent} />
 


// 子コンポーネント
<button onClick={() => this.props.myEvent(3)} >myEventを発火</button>

データフローは単一方向

データフローは単一方向、つまり「親から子へ」という一方通行である。 親のデータを子から変更することはできない。子のデータは親からもらうので、もちろん子は親のデータに依存している。 具体例で説明しよう。

親が貧乏になると一緒に子どもも一緒に貧乏になる。一方で、子どもが親からもらったお小遣いを使い果たしても親は貧乏にならない。子どもは親のお金を勝手に使うことはできない。じゃあどうするか?子どもは親に「お金が欲しい。いくら欲しい」ということを伝えるのだ。親は事前にお金がなくなったら言いなさい、と子どもにカスタムイベントを渡している。あとはそれを、子どもが引数つき(なくてもよい)で、好きなタイミングで実行するのだ。親は我が子の助けが来たらお金をあげようとずっと待ち構えている(イベントを購読)。親はそのイベントが起きるとまたお金をあげる、つまり任意の関数を実行するのである。

controlled component

controlled componentとは自分でstateを持たないコンポーネントのことである。 propsで親から全てのデータを受け取り、データを変更したい時は親からもらったイベントを発火させる。 そして親のメソッド内でデータを変更する。 つまり、その名の通り完全に親に依存するコンポーネントである。

【Git 】git switchでリモートブランチをローカルに持ってくる

f:id:lampler:20210517060943p:plain

リモートブランチと同じ名前のブランチをローカルに持ってくる

新しいコマンドのgit switchが便利! $ git switch remote_branch_name

もしうまくいかない場合は$ git fetchを実行してローカルのリモート追跡ブランチを更新してください。

リモートブランチと違う名前のブランチを作成する必要がある時

$ git checkout -b branch_name origin/branch_name branch_nameは自分で命名できる。

【Rails】formタグ内のbuttonを押すと意図せずにPostリクエストが送信されてしまう時の対処法

f:id:lampler:20210516081631p:plain

Railsで作るフォームの中で、Reactを使う必要があった。 Reactのコンポーネントで作ったボタン(<button>)を押すと、なぜかpostリクエストが飛んでしまう。

原因

<form>の<button><button type="submit">がデフォルトになっているようだ。

対処法

type="button"を追加する。

<button type="button">Increment</button>

【React】propsとstateの違い

f:id:lampler:20210509155001p:plain

props

  • コンポーネントからもらうデータ
  • 読み取り専用で変更することはできない

state

親からもらうデータを加工したい

親からもらうデータを加工したい時はstateに格納すればいい。

// 親コンポーネント
<Counter number={7}>

// 子コンポーネント
state = {
  numberFromParent: this.props.number
}

初期値を別に設定したい時は、任意の関数内でsetStateを使えばいい。

// 親コンポーネント
<Counter number={7}>

// 子コンポーネント
state = {
  numberFromParent: 0
}

// クラスのインスタンメソッドとして定義。この書き方はbabelによってコンパイルされるため、正式なJSの記法ではない。
doubleNumberFromParent = () => {
  const newNumber = this.props.number * 2
  this.setState({numberFromParent: this.state.numberFromParent + newNumber})
}

上のコードではsetStateの引数にオブジェクトを渡している。setStateにオブジェクトを渡すと最新のstateであることが保証されていないので注意が必要だ。参考 : ReactのsetStateについて整理してみた - Qiita

【Rails】静的ファイルのダウンロード機能を実装する

f:id:lampler:20210428203331p:plain

動的ファイルならコントローラーを経由する必要がある。しかし静的ファイルならもっと簡単にできる。

  1. public/foo.txtを作成

  2. download: "ダウンロードする時のファイル名"という文法でviewに書く

<%= link_to 'foo.txtをダウンロード', '/foo.txt', download: 'foo.txt' %>

ちなみにdownload: ''を書かないとその静的ファイルがそのまま表示される。 その時、rails serverのログを見ていても変化はない。何が起きているのか分からなくてクッソハマった😵

【DB設計】自己参照する多対多の関係を分かりやすく説明する

f:id:lampler:20210427203219p:plain

多対多の復習

自己参照する多対多の関係を理解するには、多対多の関係を理解する必要があります。 大学の授業と生徒の関係を例にとって考えてみます。

まずは学生目線で考えましょう。学生一人が取れる授業の数はいくつでしょうか? 1つでも2つでも3つでも、いくつでもいいですよね。0でもいいかもしれません。 つまり学生:授業 = 1:多となります。

f:id:lampler:20210427201654p:plain

次は授業目線で考えます。一つの授業に参加できる学生は何人でしょうか? 1つの講義にはたくさんの生徒が出席しますね。よって授業:生徒 = 1:多となります。 f:id:lampler:20210427201721p:plain

では学生:生徒の関係はどうなるでしょうか? どちらか一方を1と固定しても、どちらも1:多になってしまいました。このような場合は多:多となります。このように多:多の関係の見つけ方はどちらも1対多になった時となります。

ER図を書いてみよう

それでは学生と授業のデータベース設計をしてみましょう。こんな感じになります。 f:id:lampler:20210427201756p:plain

多対多の関係を管理するには中間テーブルを使います。中間テーブルを見れば、「誰が」「どの授業を」とっているのかが分かります。

select * from students_lectures;

f:id:lampler:20210427201856p:plain

自己参照する多対多の関係

ようやく本題です。今回はTwitterのフォロー関係を例に考えます。 ユーザー1人がフォローできる人数は複数です。よって1対多となります。 一方で1人のユーザーは複数人からフォローされます。したがって、フォローするユーザー:フォローされるユーザーは多:多となります。 f:id:lampler:20210427201935p:plain

ここまでは普通の多対多と同じです。しかし決定的に違う点ひとつがあります。何でしょうか?

ER図を書いてみる

friendshipsテーブルを見れば、「誰が」「誰を」フォローしているかが分かります。 f:id:lampler:20210427202034p:plain

学生と授業の例との違いは何でしょうか?

f:id:lampler:20210427202101p:plain

テーブルが一つ少ないですね。中間テーブルのfriendshipsのカラムであるfollowing_user_idfollowed_user_idはどちらもusersテーブルとつながっています。

どうやって結合する?

中間テーブルを見れば、誰が誰をフォローしているのか、誰が誰によってフォローされているのか、ということが分かります。 f:id:lampler:20210427202146p:plain

フォローしている人もフォローされている人も名前にして表示したい時はどうしましょう? usersテーブルと結合しますよね。

どちらも同じテーブルを参照しているので結合できない?

結合を考えましょう。usersテーブルをもう一つ作らないと結合できないのでしょうか?

答えはNoです。usersテーブルに別名を付けるだけで簡単に結合できます。 usersテーブルとusersテーブルを結合して新しいテーブルを作ります。このように自分自身との結合を自己結合と言います。

自己参照とは?

自己参照とは、参照するテーブル(エンティティ)が自分自身である場合をいいます。今回の例ではフォロー関係を理解するためにusersテーブルが自己参照をしています。

まとめ

  • 多対多の関係は、1対多 + 1対多である。
  • 多対多の時は、1対多となるような中間テーブルを作る。
  • 自己結合とは、1つのテーブルにそれぞれ別名を与えて2つのテーブルと見立てて結合することである。
  • 自己参照する多対多の関係は、多対多 + 自己結合で解決できる。

RubyMineの初期設定

f:id:lampler:20210427195120p:plain

ピープ音を消す

macのアラート音を消す。つまり、通知音量を0にする。slackなどの他のアプリの音は聞こえるのでこれで問題ない。 f:id:lampler:20210427194459p:plain

右の目立つ縦線を消す

  1. シフトを2回押して「wrap guide」と検索する。
  2. Hard wrap guideのForegroundのチェックを外す。

f:id:lampler:20210427194544p:plain ちなみに、ここでインデントラインの色を変更できる。

折り返しをできるようにする

Editor > General > Soft WrapsでSoft-wrapするファイルを追記する。 ファイル名はセミコロンで分けることに注意する。 全てのファイルを選択する方法を知りたい>< f:id:lampler:20210427194706p:plain

画面分割したタブ間で移動するショートカットの作成

設定画面で、左上からsplitterで検索。 Goto Next Splitterに好きなキーを割り当てる。 f:id:lampler:20210428202705p:plain

入力モード中のjjでエスケープする

右下のVのロゴをクリックして.ideavimrcに追記する。 f:id:lampler:20210428202730p:plain

inoremapはインサートモード時のキーマッピングを作成する記述である。

inoremap jj <Esc>

注意

ターミナルから読み込んでもエラーになってしまう。設定を反映するにはRubyMineを再起動する必要がある。

ショートカットキーの設定

f:id:lampler:20210915121657p:plain

.ideavimrc

"大文字小文字の区別なし
set ignorecase

"検索時に大文字を含んでいたら大/小を区別
set smartcase

"検索対象をハイライト
"ハイライトを消す場合は:noh[l]
set hlsearch

"スクロール時に表示を10行確保
set scrolloff=10

"x キー削除でデフォルトレジスタに入れない
nnoremap x "_x
vnoremap x "_x

"vv で行末まで選択
vnoremap v ^$h
"Yでカーソル位置から行末までヤンクする
nnoremap Y y$

"選択範囲のインデントを連続して変更
vnoremap < <gv
vnoremap > >gv

"ノーマルモードでもリターンキーで改行
nnoremap <CR> A<CR><ESC>
nnoremap <Space> i<Space><Esc>

" j, k による移動を折り返されたテキストでも自然に振る舞うように変更
nnoremap j gj
nnoremap k gk

" vを二回で行末まで選択
vnoremap v $h
" 動作環境との統合
" OSのクリップボードをレジスタ指定無しで Yank, Put 出来るようにする
set clipboard=unnamed,unnamedplus
"screen利用時設定
set ttymouse=xterm2
" マウスの入力を受け付ける
set mouse=a
" インサートモードから抜けると自動的にIMEをオフにする
set iminsert=2

"tab/identの設定
set shellslash
set expandtab "タブ入力を複数の空白入力に置き換える
set tabstop=2 "画面上でタブ文字が占める幅
set shiftwidth=2 "自動インデントでずれる幅
set softtabstop=2 "連続した空白に対してタブキーやバックスペースキーでカーソルが動く幅
set autoindent "改行時に前の行のインデントを継続する
set smartindent "改行時に入力された行の末尾に合わせて次の行のインデントを増減する

" ESCキー2度押しでハイライトの切り替え
nnoremap <Esc><Esc> :nohlsearch<CR><ESC>

" 入力モード中に素早くJJと入力した場合はESCとみなす
inoremap jj <Esc>

" インクリメンタル検索 (検索ワードの最初の文字を入力した時点で検索が開始)
set incsearch

カラースキームの変更

Vimだと難しいカラースキームの微調整もRubyMineなら簡単にできる。

f:id:lampler:20211019080716p:plain