Closed6
Next.jsでアプリ入門メモ(Next.js + TypeScript + TailwindCSS + TwitterAPI + Vercel)
モチベーション
- axiosなどをマトモに触ったことがないので、外部APIを使うWebアプリを作る経験をしたい
- ちょうどTwitterのAPIキー申請が通ったので使ってみたい
- 慣れるためにTypeScriptを使いたい
- Zenn本 React + TwitterAPI + Lambda でwebアプリを作ってみるが入門にとても良さそう
- こちらをベースにTwitterでいいね画像を見られるサイトを作る
Github
できたもの
練習のため、
- バックエンド部分はNext.jsのAPIルートを利用する
- hooks + TypeScriptで実装する
- ホスティングはVercelでフロント/バックエンドをまとめてデプロイする
関数コンポーネントはチュートリアルをhooks + TypeScriptで実装するを読んでおくと進めやすかった
Style
Neumorphismっぽくしてみる。
Tailwindだとtailwindcss-neumorphism
というライブラリで導入できた。
PageTransitionアニメーション
ハマったポイント
スマホのinput要素のスタイルが反映されない
Chrome Devtoolだと想定通り表示されるが、実機ではinput
要素のスタイルが変わっていない。
解決策は-webkit-appearance : none
でwebkit
のスタイルを初期化する。
Tailwindの場合はcalssName="appearance-none"
で解決できた。
TailwindCSSのお役立ちリンク
- 公式ドキュメント: だいたいドキュメントで解決する
- tailbocks: サイトデザインのサンプル集
- tailwind-elements: コンポーネントのサンプル集
- tailwind cheat sheet: ユーティリティのチートシート
- heroicons: Tailwind製のIcon
データ取得
SWR
データ取得ライブラリSWRを使うとコード量を少なくでき、無限ローディングも実装しやすそう
useEffectを使った場合
const [userId, setUserId] = useState("")
useEffect(() => {
getUser(name)
}, [name])
const getUser = async (name: string): Promise<void> => {
const user: any = await userAPI(name)
setUserId(user.id)
const userAPI = async (name: string): Promise<typeUser> => {
const response = await axios.get(`/api/user?name=${name}`);
return response.data.body.user
SWRを使った場合
const fetcher = (url) => fetch(url).then((res) => res.json())
const response = useSWR(`/api/user?name=${name}`, fetcher)
if (response.error) <div>Error</div>;
if (!response.data) <div>Loading...</div>;
const userId = response.data.body.user.id
Hooks
画面サイズを取得するHooks
画像の配置をflexboxに頼らず決めているため、画面サイズによってカラム数を変更する
画面サイズ取得はこちらのHooks実装が参考になった
Reactで画面サイズを取得するHooks
無限スクロールと自動ローディング
その他 お役立ちリンク集
OGP/メタタグ 設定
モーダル実装
Twitter API Document
動的APIルーティング
Next.js Image 最適化
<Image>
を使うことで表示する画像を最適化(キャッシュ・サイズや解像度の調整)をしてくれる。
サイトのパフォーマンスを上げるには使わない手はないが、Vercelは1000/monthの制限がある。
最適化をしない場合はunoptimized=true
に設定する
また、サイズ指定が必須のため、hight
とwidth
を設定するか、layout="fill"
を指定する。
うまくいかないときは、こちらの記事が参考になりました。
ロード完了後のアニメーション
遅延読み込みされた画像をふわっと表示したい。
ロード完了後のcallbackはonLoadingComplete
で指定できるので、こんな感じで実装。
const ImageBlock: React.FC<ImageBlockProps> = ({ image }) => {
const animationVariants = {
visible: { opacity: 1 },
hidden: { opacity: 0 },
}
const animationControls = useAnimation();
return (
<motion.div
initial={"hidden"}
animate={animationControls}
variants={animationVariants}
transition={{ ease: "easeOut", duration: 1 }}
>
<div className="flex justify-center items-center p-0 rounded-md my-2 mx-2">
<Image
src={image.url}
width={150}
height={150 * image.height / image.width}
onLoadingComplete={() => animationControls.start("visible")}
unoptimized={true}
/>
</div>
</motion.div>
);
}
export default ImageBlock;
このスクラップは2021/10/15にクローズされました