💡

next.jsによく見られたエラー

2024/06/29に公開

next.jsを使用してプロジェクトを開発した時、「client mode」のみで使えられるライブラリがある場合がよく見られます。

例えば、「react-hook-form」というライブラリを利用してフォームのチェックを行う場合が多いです。公式サイトのデモコードを見てください。

import * as React from "react"
import { useForm } from "react-hook-form"

type FormData = {
  firstName: string
  lastName: string
}

export default function App() {
  const {
    register,
    setValue,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>()
  const onSubmit = handleSubmit((data) => console.log(data))
  // firstName and lastName will have correct type

  return (
    <form onSubmit={onSubmit}>
      <label>First Name</label>
      <input {...register("firstName")} />
      <label>Last Name</label>
      <input {...register("lastName")} />
      <button
        type="button"
        onClick={() => {
          setValue("lastName", "luo") // ✅
          setValue("firstName", true) // ❌: true is not string
          errors.bill // ❌: property bill does not exist
        }}
      >
        SetValue
      </button>
    </form>
  )
}

上記のコードは、next.jsのプロジェクトではエラーが出るようになります。ターミナルに次のエラーが印刷されます。

TypeError: (0 , react__WEBPACK_IMPORTED_MODULE_2__.createContext) is not a function

開発経験によりライブラリをアップデートしたが、上記のエラーがまだ解決られない開発者が多いです。

next.jsがSSRのフレームワークでありますので、ページを作成してる時、「サーバーレンダー」はデフォルトです。「クライアントレンダー」のみで役に立つライブラリが多いです。その場合なら、ファイルの冒頭に「’use client’」の宣言を加えればいいです。そうしたら、「当ページはクライアントレンダーです」という意味をnext.jsに伝えます。

前のコードはnext.jsで効かれば、下記のようになります。

'use client'
import * as React from "react"
import { useForm } from "react-hook-form"

type FormData = {
  firstName: string
  lastName: string
}

export default function App() {
  const {
    register,
    setValue,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>()
  const onSubmit = handleSubmit((data) => console.log(data))
  // firstName and lastName will have correct type

  return (
    <form onSubmit={onSubmit}>
      <label>First Name</label>
      <input {...register("firstName")} />
      <label>Last Name</label>
      <input {...register("lastName")} />
      <button
        type="button"
        onClick={() => {
          setValue("lastName", "luo") // ✅
          setValue("firstName", true) // ❌: true is not string
          errors.bill // ❌: property bill does not exist
        }}
      >
        SetValue
      </button>
    </form>
  )
}

Discussion