- 投稿日:2020-01-20T20:44:11+09:00
React hooksとclassコンポーネントにおけるsetStateの挙動の違いについて(動かせるコードあり)
概要
こちらは以下の記事に書いたhooksとclassコンポーネントにおけるsetStateの違いを別記事にしたものです.
https://qiita.com/yseki_/items/71511db1a60ab22ee663忙しい人向けまとめ
hooksとクラス型コンポーネントのsetStateでは挙動が違う
hooksでは古いステートが引き継がれないため,更新の際は古いステートもセットする必要がある.それぞれのステート更新について
まずはhooksとclassのsetStateの違いを体験してみてください.
以下二つをhtmlファイルに貼り付け,お好きなブラウザで開いてみてください.
うまく動作しない場合,以下のリポジトリをcloneしてファイルをブラウザに貼り付けてください.
https://github.com/YutaSeki36/reactSetStateDiffクラス型コンポーネント
classComponent.html<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>ClassComponent</title> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <!-- Don't use this in production: --> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> class ClassComponent extends React.Component { constructor(props) { super(props); this.state = { a: 0, b: 0 }; this.handleChangeA = this.handleChangeA.bind(this); } handleChangeA(a) { this.setState({ a: this.state.a + a }); } render() { console.log(`a: ${this.state.a}, b: ${this.state.b}`); return ( <div> <p>a: {this.state.a}</p> <p>b: {this.state.b}</p> <button onClick={() => this.handleChangeA(1)}>a+1</button> </div> ); } } ReactDOM.render(<ClassComponent />, document.getElementById("root")); </script> </body> </html>関数型コンポーネント
FunctionComponent.html<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>FuntionComponent</title> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <!-- Don't use this in production: --> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> const FuncComponent = props => { const [state, setState] = React.useState({ a: 0, b: 0 }); const handleChangeA = a => { setState({ a: state.a + a }); }; console.log(`a: ${state.a}, b: ${state.b}`); return ( <div> <p>a: {state.a}</p> <p>b: {state.b}</p> <button onClick={() => handleChangeA(1)}>a+1</button> </div> ); }; ReactDOM.render(<FuncComponent />, document.getElementById("root")); </script> </body> </html>検証
それぞれ見た目は以下のようになるかと思います.
まずはクラス型コンポーネントの
a+1
を押してみましょう.
このように,無事更新ができました.
次は関数型コンポーネントで動作確認を行なってみましょう.
このように,hooksでステートの更新を行うと,bがundefinedになってしまいました.
解決策
公式チュートリアルに,以下のような記述があります.
しかしクラスでの this.setState とは異なり、state 変数の更新は、マージではなく必ず古い値を置換します。
とありますので,hooksによるステート更新の際は古いステートもセットする必要があります.
先ほどの関数型コンポーネントファイルのステート更新mesoddo部分を以下のように書き換えます.
funcCom.htmlconst handleChangeA = a => { // スプレッド構文を用いて、古いステートも記述する setState({ ...state, a: state.a + a }); };結び
あまりReactに慣れていない状態でhooksに手を出してしまい,初歩的なところで躓いてしまいました.
しっかりと公式ドキュメントにも書いている内容だったため,今後新たな技術を学ぶ際は公式ドキュメントに目を通そうと思いました.(誤字脱字,間違った内容などあればコメントください?♂️)
- 投稿日:2020-01-20T19:57:21+09:00
初心者によるプログラミング学習ログ 215日目
100日チャレンジの215日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
215日目は
おはようございます
— ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) January 19, 2020
215日目
仮のwebサイトコーディング
休みだったのに、たいしたことやってない#100DaysOfCode #早起きチャレンジ#駆け出しエンジニアと繋がりたい
- 投稿日:2020-01-20T19:22:53+09:00
javascript デジタルなカウントダウンタイマー
デジタルチックな良い感じのタイマーを実装したので速攻で共有します。
成果物はこんな感じです。
コードはこんな感じ。
なお、スタイリングには Bootstrap4&CSS を使用しています。
bootstrap4 downloadindex.html/* 画面の右下に配置 */ <div class="" style="position:fixed;bottom:-30px;right: -100px;z-index:100;width: 17em"> <main> <!-- 時計 --> <div class="clock text-center"> <!-- 時間 --> <div class="numbers"> <p class="hours mb-0"></p> <p class="placeholder mb-0">88</p> </div> <div class="colon"> <p class="mb-0">:</p> </div> <!-- 分 --> <div class="numbers"> <p class="minutes mb-0"></p> <p class="placeholder mb-0">88</p> </div> <div class="colon"> <p class="mb-0">:</p> </div> <!-- 秒 --> <div class="numbers"> <p class="seconds mb-0"></p> <p class="placeholder mb-0">88</p> </div> </div> <!-- タイマーを止めるボタン(機能は実装しません) --> <div class="text-center"> <button type="button" class="btn btn-light font-weight-bold my-0 px-5" >タイマーを止める</button> </div> </main> </div>お次にcss
style.css* { margin: 0; padding: 0; } main { color: #ffffff; background-color: #000000; font-family: 'digital-7', sans-serif; } main { transform: translate(-50%,-50%); padding: 15px; border: solid 5px #ffffff; } div.days { margin: 0 auto; color: #131212; } div.days .day { display: inline-block; } div.days .day p { font-size: 12px; font-weight: bold; font-family: sans-serif; text-transform: uppercase; } div.clock div{ display: inline-block; position: relative; } div.clock div p{ font-size: 30px; position: relative; z-index: 100; } div.clock .placeholder { color: #131212; position: absolute; top: 0; z-index: 50; } .light-on { color: #ffffff; }からのjavascript
index.js// 9:00:00 -> 09:00:00 って一桁の数値の場合に0を付与してあげる関数 function addZero (val){ return (val <= 9) ? ("0" + val) : val; } const second = 1000, minute = second * 60, hour = minute * 60, day = hour * 24; let countDown = new Date('Nov 10, 2020 00:00:00').getTime(), hoge = setInterval(function() { let now = new Date().getTime(), distance = countDown - now; document.getElementsByClassName('hours')[0].innerText = addZero(Math.floor((distance % (day)) / (hour))), document.getElementsByClassName('minutes')[0].innerText = addZero(Math.floor((distance % (hour)) / (minute))), document.getElementsByClassName('seconds')[0].innerText = addZero(Math.floor((distance % (minute)) / (second))); // 時間が0以下になった時の処理 if (distance < 0) { clearInterval(hoge); } }, second)デジタルチックなフォント表現をするために Digital 7フォントを使用しています。
Digital 7フォントから任意のファイルをダウンロードしてhtmlファイル内で読み込んであげてください。
- 投稿日:2020-01-20T15:56:41+09:00
【初心者】JavaScriptで「おみくじゲーム」を作ってみた
最近、JavaScriptを勉強しています。
練習として、簡単すぎる「おみくじゲーム」を作ってみました。
ちなみに、10分くらいで完成しました。笑HTMLを記述する
index.html<input type="button" value="今日のあなたの運勢は?" id="btn"> <p id="fortune"></p> <script src="main.js"></script>一番上にボタンを配置して、
その下に運勢を表示するための要素を記述しています。
JavaScriptを読み込むことも忘れずに。JavaScriptを記述する
main.jsconst btn = document.getElementById('btn'); btn.addEventListener('click', () => { const fortunes = ['大吉', '吉', '中吉', '小吉', '末吉', '凶', '大凶']; const randomNumber = Math.floor(Math.random() * fortunes.length); fortune.textContent = fortunes[randomNumber] + '!'; });クリックされるボタンを定数
btn
に代入します。
id
がbtn
の要素をgetElementById
で取ってきています。そのボタンがクリックされたときのイベントを、その下に記述しています。
運勢のうちのいずれかを、運勢を表示する要素の文字列として格納しています。7つの運勢を配列として、定数
fortunes
に格納し、
いずれかを取ってくるようにしています。運勢について
運勢の良さは、
fortunes
に記述してある順番の通りみたいです。
大吉の次が吉なのは知りませんでした。
僕はてっきり、小吉、吉、末吉の順番かと思ってました。(世界で一番どうでもいい余談)addEventListener について
addEventListener(種類, 関数, false)
という形で使います。
種類とは、イベントの種類のことで、click
やload
などがあります。
アロー関数の形であれば、先述したようにコードを書くことができます。Math.random() について
Math.random()
は、0以上1未満 の数を返します。
今回の場合、fortunes.length
が7
であるため、
Math.random() * fortunes.length
は、0以上7未満 の数を返します。Math.floor について
Math.random
だと小数も返すことになるので、都合が悪いです。
できれば整数が返ってきてほしいところです。
そこでMath.floor
を使うことで、小数点を切り捨ててくれます。そのため、
Math.floor(Math.random * fortunes.length)
は
0以上7未満の整数 すなわち 0から6のいずれかの整数 を返してくれます。おわりに
すごく簡単に「おみくじゲーム」を作ることができました。
JavaScriptの一番最初の練習としては良かったです。
これはあまりにも簡単だったので、他にもミニゲームを作ってみたいと思います。
- 投稿日:2020-01-20T10:19:05+09:00
Web制作の初心者で知っていると便利な英単語一覧
Web制作初心者制作で知っていると便利な英単語一覧
クラスの名前付けをしているとここは何てクラス名を付ければいいんだろうとか、参考にしたいソースを見た時にこれ何て読むのだろうとか、書けるけど読み方がわからなくて同僚と話すときにタジタジになってしまうなどあると思います。
web制作初心者の方や英語なんて日本にいるんだから使わないわ!と思っていた人や、英語の勉強を避けてきた人などが参考になればいいなと思ってまとめてみました。
よく使うやつと誤字しやすいつを載せています。クラス名一覧
wrapper (ラッパー)
・要素を内包する
もっとわかりやすく言うとサラ○ラップのラップのように包み込むということ
・タイプミスしやすいので注意wrap(ラッパー)
・wrapperをただ略しただけcontainer(コンテナ)
・コンテナ
スペル的に語尾を伸ばしたくなるけど伸ばさない方が伝わりやすいcontent(コンテント)
・内容、中身
・コンテンツともいう人はいるcommon(コモン)
・共通product(プロダクト)
・製品、商品concept(コンセプト)
・コンセプト
conseptではないので注意index(インデックス)
・索引inquiry(インクアリー)
・問い合わせ
クアリーって発音しながらquaryではなくquiryなので注意access(アクセス)
・アクセス
cとsが2つなので注意privacy(プライバシー)
・プライバシー
sではなくてcなので注意input(インプット)
・入力confirm(コンファーム)
・確認
ファームって発音しておきながらfarmではなくてfirmなので注意finish(フィニッシュ)
・完了section(セクション)
・部分description(ディスクリプション)
・説明summary(サマリー)
・概要inner(インナー)
・内側outer(アウター)
・外側agree(アグリー)
・同意address(アドレス)
・住所
dとsが二つずつあるので注意active(アクティブ)
・アクティブ、有効disabled(ディセイブルド)
・無効icon(アイコン)
・アイコンbreadcrumb(ブレッドクラム)
・パンクズリスト
普段つかわない言葉なんで馴染みがないのでわかりにくいですねnavigation(ナビゲーション)
・ナビゲーションnav(ナビゲーション)
・navigationを略しただけbutton(ボタン)
・ボタン
botton やbottom のように間違えてしますことが多いので注意bottom(ボトム)
・下部
ちなみに上からtop(トップ)、middle(ミドル)、bottom(ボトム)となる
共に働くWebエンジニアを募集しています!
不動産SHOPナカジツでは自社サービスを作っていく仲間を募集しています。
詳しくはWantedlyからお問い合わせください。
- 投稿日:2020-01-20T10:19:05+09:00
Web制作初心者制作で知っていると便利な英単語一覧
Web制作初心者制作で知っていると便利な英単語一覧
クラスの名前付けをしているとここは何てクラス名を付ければいいんだろうとか、参考にしたいソースを見た時にこれ何て読むのだろうとか、書けるけど読み方がわからなくて同僚と話すときにタジタジになってしまうなどあると思います。
web制作初心者の方や英語なんて日本にいるんだから使わないわ!と思っていた人や、英語の勉強を避けてきた人などが参考になればいいなと思ってまとめてみました。
よく使うやつと誤字しやすいつを載せています。クラス名一覧
wrapper (ラッパー)
・要素を内包する
もっとわかりやすく言うとサラ○ラップのラップのように包み込むということ
・タイプミスしやすいので注意wrap(ラッパー)
・wrapperをただ略しただけcontainer(コンテナ)
・コンテナ
スペル的に語尾を伸ばしたくなるけど伸ばさない方が伝わりやすいcontent(コンテント)
・内容、中身
・コンテンツともいう人はいるcommon(コモン)
・共通product(プロダクト)
・製品、商品concept(コンセプト)
・コンセプト
conseptではないので注意index(インデックス)
・索引inquiry(インクアリー)
・問い合わせ
クアリーって発音しながらquaryではなくquiryなので注意access(アクセス)
・アクセス
cとsが2つなので注意privacy(プライバシー)
・プライバシー
sではなくてcなので注意input(インプット)
・入力confirm(コンファーム)
・確認
ファームって発音しておきながらfarmではなくてfirmなので注意finish(フィニッシュ)
・完了section(セクション)
・部分description(ディスクリプション)
・説明summary(サマリー)
・概要inner(インナー)
・内側outer(アウター)
・外側agree(アグリー)
・同意address(アドレス)
・住所
dとsが二つずつあるので注意active(アクティブ)
・アクティブ、有効disabled(ディセイブルド)
・無効icon(アイコン)
・アイコンbreadcrumb(ブレッドクラム)
・パンクズリスト
普段つかわない言葉なんで馴染みがないのでわかりにくいですねnavigation(ナビゲーション)
・ナビゲーションnav(ナビゲーション)
・navigationを略しただけbutton(ボタン)
・ボタン
botton やbottom のように間違えてしますことが多いので注意bottom(ボトム)
・下部
ちなみに上からtop(トップ)、middle(ミドル)、bottom(ボトム)となる
- 投稿日:2020-01-20T09:35:04+09:00
Googleの検索結果に意図したファビコンが表示されない
背景
GoogleのPC検索結果にファビコンが表示されるようになった。
が、指定のファビコン画像ではなく、タッチアイコンに指定している別の画像が表示されてしまっていた。現状
問題のサイトではアイコン類を以下のように指定。
<link rel="shortcut icon" href="/favicon.ico"> <link rel="apple-touch-icon" sizes="192x192" href="/touch-icon.png">タブやお気に入りのファビコンは
favicon.ico
が表示されているのだが、
検索結果はtouch-icon.png
が表示されてしまっている。検索結果でも
favicon.ico
を表示したい。Googleのガイドライン
Googleのガイドラインは以下のページに記載されている。
疑いポイント1:アイコンのサイズ
ガイドライン では以下のように指定されている。
ファビコンのサイズが 48 ピクセルの倍数になっていること(例: 48 x 48 ピクセル、96 x 96 ピクセル、144 x 144 ピクセルなど)。SVG ファイルの場合は、サイズに関して特別な指定はありません。有効なファビコン形式は、すべてサポートされています。Google では画像サイズを 16 x 16 ピクセルに変換するため、その解像度で適切に表示されるか、あらかじめご確認ください。16 × 16 ピクセルのファビコンは指定しないでください
対して、問題のサイトのアイコンのサイズは
64 x 64
。
サイズ違反が原因?疑いポイント2:アイコン系の記載順
ガイドライン では以下のように指定されている。
ホームページのヘッダーに次の構文の タグを追加します。
rel
次のいずれかを指定できます。
・"shortcut icon"
・"icon"
・"apple-touch-icon"
・"apple-touch-icon-precomposed"対して、問題のサイトではアイコン系の設定を以下のように2つ記載している。
<link rel="shortcut icon" href="/favicon.ico"> <link rel="apple-touch-icon" sizes="192x192" href="/touch-icon.png">記載順から
apple-touch-icon
がファビコンとして認識されている?結論
「疑いポイント:2」のアイコンの記載順が原因っぽかった。
以下のように記載順を修正することで、Googleの検索結果にfavicon.ico
が表示されるようになった。
※ただし、反映まで2日ほどかかった。<link rel="apple-touch-icon" sizes="192x192" href="/touch-icon.png"> <link rel="shortcut icon" href="/favicon.ico">サイズについては、
64 x 64
のままで表示されるようになったので、
ガイドラインに沿っていなくてもよしなにやってくれるようです。
- 投稿日:2020-01-20T09:10:47+09:00
[自動更新が止まらない]RailsでJavascriptファイル(html機能)を用いて自動更新機能実装をした時に、ブラウザ上の繰り返し表示が止まらないエラーの解決例
1.エラーの様子と間違っていたファイル
まず筆者が起こしたエラーは下のものです
<エラーの様子(gifなので動かない場合は画像をクリックしてご確認ください)>
言葉で表現すると、仕様としてはsendボタンを押したら、1回だけ「家に帰ってお母さんに報告だ!」が出て(ブラウザ上の)更新が止まる予定でした。(裏では1秒に1度更新する設定にはしていますが、見た目に反映させない仕様を目指していました。)
しかしご覧の通り表面上ループを抜けられずコメントがずっと繰り返されてしまいます。
(これでは永遠にお母さんに報告し続けることとなってしまいます。)困ったなと思いながら、この表記をするファイルにlinkを組んである「qiitaに聞いた」をクリックするとコメントは1度のみ投稿されたこととなっています(データベースへの取得は一回だけと設定ができている状態でした。)
<間違いがあったファイル(下記は間違っている状態です)>
app/assets/javascripts/message.js$(function(){ function buildHTML(message){ if ( message.image ) { var html = `<div class="chat-main__message-list" data-message-id=${message.id}> <div class="chat-main__message-list__name"> ${message.user_name} <div class="chat-main__message-list__name__date"> ${message.created_at} </div> </div> <div class="chat-main__message-list__comment"> <p class="chat-main__message-list__comment__content"> ${message.content} </p> </div> <img src=${message.image} > </div>` return html; } else { var html = `<div class="chat-main__message-list" data-message-id=${message.id}> <div class="chat-main__message-list__name"> ${message.user_name} <div class="chat-main__message-list__name__date"> ${message.created_at} </div> </div> <div class="chat-main__message-list__comment"> <p class="chat-main__message-list__comment__content"> ${message.content} </p> </div> </div>` return html; }; } $('#new_message').on('submit', function(e){ e.preventDefault(); var formData = new FormData(this); var url = $(this).attr('action') $.ajax({ url: url, type: "POST", data: formData, dataType: 'json', processData: false, contentType: false }) }) var reloadMessages = function() { //カスタムデータ属性を利用し、ブラウザに表示されている最新メッセージのidを取得 last_message_id = $('.message:last').data("message-id"); $.ajax({ //ルーティングで設定した通りのURLを指定 url: "api/messages", //ルーティングで設定した通りhttpメソッドをgetに指定 type: 'get', dataType: 'json', //dataオプションでリクエストに値を含める data: {id: last_message_id} }) .done(function(messages) { if (messages.length !== 0) { //追加するHTMLの入れ物を作る var insertHTML = ''; //配列messagesの中身一つ一つを取り出し、HTMLに変換したものを入れ物に足し合わせる $.each(messages, function(i, message) { insertHTML += buildHTML(message) }); //メッセージが入ったHTMLに、入れ物ごと追加 $('.messages').append(insertHTML); $('.messages').animate({ scrollTop: $('.messages')[0].scrollHeight}); $("#new_message")[0].reset(); // $('form')[0].reset(); $('.chat-main__message-form__new_message__send__btn').attr('disabled', false); } }) .fail(function() { console.log('error'); }); }; // }); if (document.location.href.match(/\/groups\/\d+\/messages/)) { setInterval(reloadMessages, 7000); } });app/views/messages/_message.html.haml.message{data: {message: {id: message.id}}} .chat-main__message-list .chat-main__message-list__name =message.user.name .chat-main__message-list__name__date =message.created_at.strftime("%y年%m月%d日%H時%M分") .chat-main__message-list__comment - if message.content.present? %p.chat-main__message-list__comment__content = message.content = image_tag message.image.url, class: 'chat-main__message-list__comment__content__image' if message.image.present?2.エラー元発見までの過程
解決までの道のりから記載した方がおそらく類似のエラーでも発見がしやすくなり皆さんのエラーへのお力になれると思うので過程から書かせていただきます。お急ぎの方は3.原因と解決方法をご覧ください。(エラーの元がわかれば原因と解決がやりやすくなると考え先に記載しています。原因究明だけ読まれると筆者のエラーと全く同じの場合しか解決できなく、せっかく時間をかけて調べられた内容で応用を効かせること(他のエラーの対処に役立たせること)ができず勿体無いと思っています。ですので、ぜひこの章もご覧ください)
<エラー元発見への過程>
①エラーの挙動から見てフロントに関する記述(HTMLのコード)がおかしいんだろうな②フロント(HTMLのコード)ならGoogleChromeの検証機能だ!ということで下の画像のように検証を開いてみました
③繰り返し表示されてるコメントの"data-message-id=44"はclass名が"chat-main__message-list"で、正しく表記されている上のコメントの"data-message-id=42"や"data-message-id=43"のクラス名は"massage"になってる!と気づきます
④③のタイミングで正しく表記された部分とエラーの部分の差異がエラーの元となっていると予想し、自動更新(JavaScriptファイル)のchat-main__message-listの部分がおかしいんだなと気づくことができ探しに行けたという流れでした
このように、挙動を見ながら正しい部分と間違った部分を比べて差異を見つけることがエラー発見の基本となり、これ以外のエラーでも役立つ作業なのです。
3.原因と解決方法
<原因>
まず結論から言いますとこのように繰り返されてしまった原因は、id振り分け機能の不全でした。詳しく説明しますと、当初の予定ではまずapp/controllers/api/messages_controller(更新機能を取り付けるためのコントローラ)の部分で「idが以前のものより大きいものを全て受け取る」ようにする。
次に更新(api)でidを得た後、大元の"app/controllers/messages_controller"で現在振り分け済みのidと更新(api)で得たidを同期する。
すると、apiで入れ込もうとするidが振り分け済みのidとイコールの関係になるので一回しか表示されないとなるはずでした
ところが、"app/controllers/api/messages_controller"で手に入れてくるidのクラス名が間違っているので"app/controllers/messages_controller"で同期できずに繰り返し表示されるという始末でした。(じゃあなんでlinkボタンで更新すると直るのかと言われると想像の話となってしまうのですが、検証のid振り分けの挙動から推測するに、railsのgemのどれかで、他からのアクセス時に描画に関するidとclass名が大元のコントローラと一致しないものを大元に合わせた修正を行ってくれるものがあるんじゃないかと思っています。浅学で申し訳ない。)<解決方法>
親クラスが合っていればidで整合を取れるので、
①JavaScriptファイル(app/asset/javascripts/massage.js)のHTML記載の親クラスのみmessageに変えるapp/assets/javascripts/message.js$(function(){ function buildHTML(message){ if ( message.image ) { var html = `<div class="message" data-message-id=${message.id}> #クラス名を変えました <div class="chat-main__message-list__name"> ${message.user_name} <div class="chat-main__message-list__name__date"> ${message.created_at} </div> </div> <div class="chat-main__message-list__comment"> <p class="chat-main__message-list__comment__content"> ${message.content} </p> </div> <img src=${message.image} > </div>` return html; } else { var html = `<div class="message" data-message-id=${message.id}> #クラス名を変えました <div class="chat-main__message-list__name"> ${message.user_name} <div class="chat-main__message-list__name__date"> ${message.created_at} </div> </div> <div class="chat-main__message-list__comment"> <p class="chat-main__message-list__comment__content"> ${message.content} </p> </div> </div>` return html; }; } #以下は同じです②app/views/messages/_massages.html.haml(大元のコントローラと繋がっているview)で.messageを1番目の親とするネスト形態とする
app/views/messages/_message.html.haml.message{data: {message: {id: message.id}}} #以下のインデントを全て一つ下げました .chat-main__message-list .chat-main__message-list__name =message.user.name .chat-main__message-list__name__date =message.created_at.strftime("%y年%m月%d日%H時%M分") .chat-main__message-list__comment - if message.content.present? %p.chat-main__message-list__comment__content = message.content = image_tag message.image.url, class: 'chat-main__message- list__comment__content__image' if message.image.present?この①と②でこのバグは解消されます
<解決した画面(gifなので動かない場合は画像をクリックしてご確認ください)>
ご参考になればと思います。
4.参考(gif作成に参考にさせてもらった記事のリンク、関連ファイルの内容の提示)
参考までに、gif作成の参考サイトへのリンクと、修正はしなかったけど、ここまでに名前がでてきたファイルを下に貼付しておきます
<gif作成の参考にさせてもらった記事へのリンク>
<api用コントローラ>
app/controllers/api/messages_controller.rbclass Api::MessagesController < ApplicationController def index # ルーティングでの設定によりparamsの中にgroup_idというキーでグループのidが入るので、これを元にDBからグループを取得する group = Group.find(params[:group_id]) # ajaxで送られてくる最後のメッセージのid番号を変数に代入 last_message_id = params[:id].to_i # 取得したグループでのメッセージ達から、idがlast_message_idよりも新しい(大きい)メッセージ達のみを取得 @messages = group.messages.includes(:user).where("id > #{last_message_id}") end end<大元のコントローラ>
app/controllers/messages_controller.rbclass MessagesController < ApplicationController before_action :set_group def index @message = Message.new @messages = @group.messages.includes(:user) end def create @message = @group.messages.new(message_params) if @message.save respond_to do |format| format.json end else @messages = @group.messages.includes(:user) flash.now[:alert] = 'メッセージを入力してください。' render :index end end private def message_params params.require(:message).permit(:content, :image).merge(user_id: current_user.id) end def set_group @group = Group.find(params[:group_id]) end end
- 投稿日:2020-01-20T08:59:07+09:00
社内の月朝ゆるもく会で作ったバーチカルメニュー
毎週月曜朝、7:00~8:30くらいでゆるっともくもく会をやり始めました。
頑張って早起きして、アウトプット出していきたい。。。成果物
See the Pen circle by UMA (@umaniel) on CodePen.
その昔、横方向の開きメニューを作ったことがあったので、縦方向でも作ってみようと思い、やってみました。
やってること
特に難しいことはしておらず、classの付け替えでheightが変わるだけです。
[class*="home--"].active { height: 100%; } [class*="home--"].disactive { height: 0%; }純javascriptはclassの付け替えが面倒。。。
const home = document.querySelectorAll("div[class*='home--']"); const active = _self => { const selfClass = _self.className.replace(/^(home--(top|bottom|center)).*/, "$1"); for (i = 0; i < home.length; i++) { home[i].className = home[i].className.replace(/^(home--(top|bottom|center)).*/, "$1"); home[i].className += selfClass == home[i].className ? " active" : " disactive"; } }; const disactive = () => { for (i = 0; i < home.length; i++) { home[i].className = home[i].className.replace(/^(home--(top|bottom|center)).*/, "$1"); } };
- 投稿日:2020-01-20T02:31:39+09:00