20211124のCSSに関する記事は2件です。

メッセージを送信後、画面最下部まで自動でスクロールする(React)

何をやるのか LINEのように、チャット画面で新規メッセージを送信後、画面最下部まで自動でスクロールする機能の実装方法について解説します。 Reactで作ったSPAが前提の方法です。 1. チャット画面を実装 まずはサンプルとなるチャット画面を実装。 ChatScreen.jsx import React, { useState } from 'react'; import './ChatScreen.css'; // ダミーデータを生成 const dummyMessages = Array(30) .fill({}) .map((_, index) => ({ id: index, content: `ダミーメッセージ #${index + 1}`, })); export const ChatScreen = () => { const [messages, setMessages] = useState(dummyMessages); const [inputValue, setInputValue] = useState(''); const onSendMessage = () => { setMessages(messages.concat({ id: messages.length + 1, content: inputValue })); setInputValue(''); }; return ( <div className='container'> <ul className='messages-container'> {messages.map((message, index) => ( <li key={message.id} className='message'> <p>{message.content}</p> </li> ))} </ul> <div className='input-container'> <input type='text' className='input' value={inputValue} onChange={({ target }) => setInputValue(target.value)} /> <button className='button' onClick={onSendMessage}> 送信 </button> </div> </div> ); }; ChatScreen.css .container { overflow-y: overlay; display: inline-block; } .messages-container { display: flex; flex-direction: column; padding: 50px; margin-bottom: 100px; } .message { padding: 5px 20px; background-color: #dcf8c6; display: block; border-radius: 10px; margin-top: 10px; margin-bottom: 10px; clear: both; } .input-container { display: flex; flex-direction: column; justify-content: space-around; height: 100px; padding: 5px; width: 100%; position: fixed; bottom: 30px; } .input { width: 60%; margin: auto; border: 1px silver solid; font-size: 15px; line-height: 40px; } .button { width: 100px; margin: auto; } 仕上がりはこんな感じです。 2. Reactのrefを使って末尾のメッセージを管理 (1) useRefでrefを定義 ChatScreen.tsx const footRef = useRef(null) React HookのuseRefでfootRefオブジェクトを定義。 デフォルト値はnull。 (2) 末尾のメッセージへrefを付与 ChatScreen.jsx {messages.map((message, index) => ( <li key={message.id} className='message'> <p>{message.content}</p> {/* 以下の一行を追加 */} {index === messages.length - 1 && <div ref={footRef}></div>} </li> ))} messages配列の末尾の要素、つまり最下部に表示されるメッセージへfootRefを付与。 3. useLayoutEffectで自動スクロール ChatScreen.jsx useLayoutEffect(() => { footRef.current.scrollIntoView(); }, [messages]); useLayoutEffect関数を記述し、第二引数の配列に渡された値(messages)の変更があるたびに, "footRef.current.scrollIntoView()"で最下部の要素を画面上に表示。 最終的なコードは以下。 ChatScreen.jsx import React, { useLayoutEffect, useRef, useState } from 'react'; import './ChatScreen.css'; // ダミーデータ const dummyMessages = Array(30) .fill({}) .map((_, index) => ({ id: index, content: `ダミーメッセージ #${index + 1}`, })); export const ChatScreen = () => { const [messages, setMessages] = useState(messagesData); const [inputValue, setInputValue] = useState(''); const footRef = useRef(null); const onSendMessage = () => { setMessages(messages.concat({ id: messages.length + 1, content: inputValue })); setInputValue(''); }; useLayoutEffect(() => { footRef.current.scrollIntoView(); }, [messages]); return ( <div className='container'> <ul className='messages-container'> {messages.map((message, index) => ( <li key={message.id} className='message'> <p>{message.content}</p> {/* 以下の一行を追加 */} {index === messages.length - 1 && <div ref={footRef}></div>} </li> ))} </ul> <div className='input-container'> <input type='text' className='input' value={inputValue} onChange={({ target }) => setInputValue(target.value)} /> <button className='button' onClick={onSendMessage}> 送信 </button> </div> </div> ); }; こんな感じで自動スクロールが実現できました。 今回はチャット画面を題材として扱いましたが、こちらのテクニックは割といろんな場面で応用できるのではないかなと思います。 こちらあくまで一方法となりますのでご参考までに。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javascript カレンダー作成

はじめに 本稿では下記動画にあるソースコードを解説します。 動画にあるカレンダーは、他のライブラリに依存しない実装になっています。 簡単なカレンダーが表示できれば十分、かつ、依存ライブラリを増やしたくない場合などで使えると思います。 ソースコード https://github.com/lashaNoz/Calendar カレンダー作成に必要な変数 // 今日の日付 EX) 2021/11/24 const date = new Date(); // 月末 EX) 2021/11/30 const lastDay = new Date(date.getFullYear(),date.getMonth() + 1,0).getDate(); // 先月末 EX) 2021/10/31 const prevLastDay = new Date(date.getFullYear(),date.getMonth(),0).getDate(); // 月初の曜日。0 ~ 6 = 日曜 ~ 土曜 EX) 1 (2021/11/1は月曜日) const firstDayIndex = date.getDay(); // 月末の曜日。 EX) 2 (2021/11/30は火曜) const lastDayIndex = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDay(); 日付表示 calndar.js // 1.前の月 // firstDayIndexは月初の曜日。EX) 1(月曜) // prevLastDayは先月の末日。EX) 31 (10/31) for(let i = firstDayIndex; i>0; --i){ days += `<div class="prev-date">${prevLastDay - i + 1}</div>`; } // 2.今月 const today = new Date().getDate(); for(let i = 1; i<=lastDay; ++i){ if(i === today){ days += `<div class="today">${i}</div>`; } else { days += `<div>${i}</div>`; } } // 3.次の月 const sunday = 6; for(let i = 1; i<=sunday-lastDayIndex; ++i){ days += `<div class="prev-date">${i}</div>`; } 前月、次月表示ボタン押下時処理 document.querySelector(".prev").addEventListener("click", () => { // 前月のカレンダーを表示 date.setMonth(date.getMonth() - 1); renderCalendar(); }); document.querySelector(".next").addEventListener("click", () => { // 次月のカレンダーを表示 date.setMonth(date.getMonth() + 1); renderCalendar(); }); DOM読み込み完了後にJavascript実行(おまけ) 動画の実装だと、javascriptを読み込むタイミングによってはカレンダーが表示されません。 window.onload内に処理を定義することで、DOM読み込みが完了した後に処理が実行されます。 DOMContentLoaded イベントに処理を定義すると、DOM読み読み込み完了後に処理が実行されます。 window.addEventListener('DOMContentLoaded', () => { // DOM読み込み完了のタイミングで実行したい処理 const date = new Date(); const renderCalendar = function(){ date.setDate(1); ~~~ });
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む