Next.jsで非同期処理が走らなくて困った話
こんにちは。ひろっきーです。
現在ITエンジニア転職を目指して現在、独学9ヶ月目で日々学習、現在はNext.js、TypeScript などを学習しており、ポートフォリオとしてSNSアプリケーションを作成しています。
今回はこのSNSアプリの認証ページを作成するにあたって非同期処理で詰まった部分を共有したいと思います。
使用技術
- React
- Next.js
- Typescript
- TailwindCSS
- Firebase Authentication
- Material UI
- React-redux-toolkit
- ...etc
実際のコード(長いので一部抜粋)
const Auth: NextPage = () => {
const router = useRouter();
const [isLogin, setIsLogin] = useState(true);
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
//onChangeなどは省略...
//新規ユーザー登録処理
const userRegister = async () => {
const authUser = await auth.createUserWithEmailAndPassword(email, password);
await authUser.user?.updateProfile({
displayName: username,
photoURL: "",
});
dispatch(
updateUserProfile({
displayName: username,
photoUrl: "",
})
);
router.push("/");
return (
<div className="max-w-md w-full m-auto justify-center ">
<div>
<form className="mt-8 space-y-6">
<input type="hidden" name="remember" value="true" />
<div className="rounded-md shadow-sm -space-y-px">
<div>
<input
name={isLogin ? "username" : "email"}
type="text"
autoComplete={isLogin ? "username" : "email"}
required
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
placeholder={isLogin ? "Username " : "Email"}
value={isLogin ? username : email}
onChange={isLogin ? onChangeUserName : onChangeEmail}
/>
</div>
<div>
<input
name="password"
type="password"
autoComplete="current-password"
required
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
placeholder="Password"
value={password}
onChange={onChangePassword}
/>
</div>
</div>
<div className="flex items-center justify-center">
<div className="text-sm">
<span
onClick={() => setIsLogin(!isLogin)}
className="cursor-pointer font-medium text-gray-700 hover:text-blue-500"
>
Create New User
</span>
{isLogin ? null : (
<div>
<form>
.
.
.
省略
.
.
</form>
</div>
)}
</div>
</div>
<div>
<button
disabled={
isLogin
? !email || password.length < 6
: !username || !email || password.length < 6
}
onClick={
isLogin
? async () => {
try {
await login();
} catch (err) {
alert(err.message);
}
}
: async () => {
try {
await userRegister();
} catch (err) {
alert(err.message);
}
}
}
{isLogin ? "Login" : "Create New User"}
</button>
</form>
</div>
);
};
export default Auth;
};
実際の見た目はコチラ ↓
早速ログインしてみようとすると...
はい動きません。。。
画面遷移の挙動はするものの、またauthページに戻って来てしまいます。。。
Firebase Authenticationを確認してもユーザー情報は所得出来ていない!?
エラーメッセージなどもなく、自身の非同期関数の書き方がおかしいと思い非同期処理の学習をひたすら復習、、、
色々コードを書き換えて行っても全く挙動変わらず。。。
かれこれ4日間これと格闘することに、、、、
原因と対策
ずっとJsの記法がおかしいと思っていて、全くコードが動かせず自身を失うひろっきー、、、、
JavaScriptが好きで毎日続けたけどかなり大きな挫折を味わい途方に暮れる、、、
しかし、一からコードを再度見直すと
ん??
<form>
のところに<form noValidate>
を書いたら意図した挙動に(歓喜)
そう原因はJsの構文ではなく、HTMLタグの属性が邪魔をしていたのが原因でした(汗)
今回は<button>
タグにonClick
で処理を書いてたのでより発見が遅れました、、、
noValidate属性を追加することでformのsubmitを抑えることが出来ました。
つまり、Jsの非同期関数を実行する前にformタグのsubmitが実行されてlogin関数やuserRegister関数が走らないということでした。。。
まとめ
意外なところに罠が潜んでおり、これだけで4日間を費やしてしまいましたが、継続していれば必ず解決出来ますので、皆さんも毎日コツコツと自身の引き出しを増やしてガンバりましょう!!
Discussion