Closed6

Next.jsでアプリ入門メモ(Next.js + TypeScript + TailwindCSS + TwitterAPI + Vercel)

marushomarusho

モチベーション

  • axiosなどをマトモに触ったことがないので、外部APIを使うWebアプリを作る経験をしたい
  • ちょうどTwitterのAPIキー申請が通ったので使ってみたい
  • 慣れるためにTypeScriptを使いたい
  • Zenn本 React + TwitterAPI + Lambda でwebアプリを作ってみるが入門にとても良さそう
  • こちらをベースにTwitterでいいね画像を見られるサイトを作る

Github

https://github.com/marushosummers/dev-twitter-art-gallery

できたもの

https://garoo.marusho.io/

marushomarusho

Style

Neumorphismっぽくしてみる。
Tailwindだとtailwindcss-neumorphismというライブラリで導入できた。

https://github.com/sambeevors/tailwindcss-neumorphism

PageTransitionアニメーション

ハマったポイント

スマホのinput要素のスタイルが反映されない

Chrome Devtoolだと想定通り表示されるが、実機ではinput要素のスタイルが変わっていない。

解決策は-webkit-appearance : nonewebkitのスタイルを初期化する。
Tailwindの場合はcalssName="appearance-none"で解決できた。

TailwindCSSのお役立ちリンク

marushomarusho

データ取得

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

無限スクロールと自動ローディング

marushomarusho

Next.js Image 最適化

<Image>を使うことで表示する画像を最適化(キャッシュ・サイズや解像度の調整)をしてくれる。
サイトのパフォーマンスを上げるには使わない手はないが、Vercelは1000/monthの制限がある。

https://vercel.com/docs/concepts/limits/fair-use-policy#typical-monthly-usage-guidelines

最適化をしない場合はunoptimized=trueに設定する

https://nextjs.org/docs/api-reference/next/image#unoptimized

また、サイズ指定が必須のため、hightwidthを設定するか、layout="fill"を指定する。
うまくいかないときは、こちらの記事が参考になりました。

ロード完了後のアニメーション

遅延読み込みされた画像をふわっと表示したい。

https://stackoverflow.com/questions/65546293/how-can-i-add-a-fade-in-animation-for-nextjs-image-when-it-loads

ロード完了後の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にクローズされました