はじめに
Udemyハンズオン中にクリックしたユーザーの情報をコンソールで取得できない症状があり、こちらの解決方法について共有します。
バージョン
React v19
下記のように記述していました。
UserManegement.tsx
import React, { memo, useCallback, useEffect } from "react"
import { Center, Spinner, useDisclosure, Wrap, WrapItem } from "@chakra-ui/react"
import { UserCard } from "../organisms/user/UserCard"
import { useAllUsers } from "../hooks/useAllUsers";
import { UserDetailModal } from "../organisms/user/UserDetailModal";
import { useSelectUser } from "../hooks/useSelectUser";
export const UserManagement: React.FC = memo(() => {
const { isOpen, onOpen, onClose } = useDisclosure()
const { getUsers, loading, users } = useAllUsers();
const { onSelectUser, selectedUser } = useSelectUser();
console.log("UserManagementでのusers:", users); // usersの中身をここでも確認 取得OK
useEffect(() => getUsers(), [getUsers])
const onClickUser = useCallback((id: number) => {
console.log("クリックされたユーザーID",id); // ここでid取得はできている
onSelectUser({ id, users })
onOpen()}, [])
return (
<>
{loading ? (
<Center h="100vh">
<Spinner />
</Center>
) : (
<Wrap p={{ base: 4, md: 10 }}>
{users.map((user) => (
<WrapItem key={user.id} mx="auto">
<UserCard id={user.id} imageUrl="https://picsum.photos/200" userName={user.username} fullName={user.name} onClick={onClickUser} />
</WrapItem>
))}
</Wrap >
)}
<UserDetailModal isOpen={isOpen} onClose={onClose} />
</>
)
})
.useSelectUser.ts
import { useCallback, useEffect, useState } from 'react'
import { User } from '../../types/api/user';
type Props = {
id: number;
users: Array<User>;
}
export const useSelectUser = () => {
const [selectedUser, setSelectedUser] = useState<User | null>(null); // 初期値は未選択のためnull
const onSelectUser = useCallback((props: Props) => {
const { id, users} = props;
// usersが空でないかを確認する
console.log("onSelectUser呼び出し時のusers", users); // usersの中身しても空
const targetUser = users.find((user) => user.id === id) // usersという配列から、userという任意名の要素を1つずつ取出し、そのuser.idとPropsのidが=のものを取得する
console.log("idが一致したもの", targetUser); // undefinedが返る
setSelectedUser(targetUser ?? null); // 上記で取得したユーザー情報をset関数へ渡す ?? 左辺がnullまたはundifinedの時に右辺を返す
}, []);
return { onSelectUser, selectedUser }
}
解決方法
UserManegement.tsx
import React, { memo, useCallback, useEffect } from "react"
import { Center, Spinner, useDisclosure, Wrap, WrapItem } from "@chakra-ui/react"
import { UserCard } from "../organisms/user/UserCard"
import { useAllUsers } from "../hooks/useAllUsers";
import { UserDetailModal } from "../organisms/user/UserDetailModal";
import { useSelectUser } from "../hooks/useSelectUser";
export const UserManagement: React.FC = memo(() => {
const { isOpen, onOpen, onClose } = useDisclosure()
const { getUsers, loading, users } = useAllUsers();
const { onSelectUser, selectedUser } = useSelectUser();
console.log("UserManagementでのusers:", users); // usersの中身をここでも確認 取得OK
useEffect(() => getUsers(), [getUsers])
const onClickUser = useCallback((id: number) => {
console.log("クリックされたユーザーID",id);
onSelectUser({ id, users })
onOpen()}, [users]) // ← 依存配列に記述を追加
return (
<>
{loading ? (
<Center h="100vh">
<Spinner />
</Center>
) : (
<Wrap p={{ base: 4, md: 10 }}>
{users.map((user) => (
<WrapItem key={user.id} mx="auto">
<UserCard id={user.id} imageUrl="https://picsum.photos/200" userName={user.username} fullName={user.name} onClick={onClickUser} />
</WrapItem>
))}
</Wrap >
)}
<UserDetailModal isOpen={isOpen} onClose={onClose} />
</>
)
})
参考
終わりに
依存配列について学ぶことができました。