I am trying to map a card component with user data which I get from the jsonplaceholder using axios. However, when I tried, it returns with "TypeError: Cannot read properties of undefined (reading 'map')". I tried all the solutions on the web without success. Please help!
Here is the code that declared 'users';
export const useAllUsers = () => {
const [users, setUsers] = useState<Array<User>>()
const getUsers = useCallback(() => {
axios
.get<Array<User>>('https://jsonplaceholder.typicode.com/users')
.then(res => {
setUsers(res.data)})
.catch(() => {
return <MessageError />
})
.finally(()=>{
setLoading(false)
})
}, [])
return { getUsers, loading, users }
}
Then, I tried to map the 'users' get the all the user data as below:
export const UserManagement: VFC = memo(() => {
const { getUsers, users, loading } = useAllUsers()
useEffect(() => getUsers(), [])
return (
<>
{loading ? (
<div className=' flex justify-center items-center'>
<div className='animate-spin rounded-full h-32 w-32 border-b-2 border-gray-900'></div>
</div>
) : (
<div
className='grid
grid-cols-2 mb-16 md:grid-cols-3 lg:grid-cols-4 sm:px-6 md:px-16'
>
<div className='grid mx-auto'>
{users.map(user => (
<UserCard
key={user.id}
userName={user.username}
imageUrl='https://source.unsplash.com/random'
userId={user.name}
/>
))}
</div>
</div>
)}
</>
)
})
User type is just having a bunch of types for user data, so I think this is not the problem, I guess?
export type User = {
id: number
name: string
username: string
email: string
hobbies: string
}
CodePudding user response:
I think your trying to map your users before the get
request is done so it's undefined. Try something like
{
users &&
users.map((user) => (
<UserCard
key={user.id}
userName={user.username}
imageUrl="https://source.unsplash.com/random"
userId={user.name}
/>
));
}
CodePudding user response:
If your response is returning an array I would suggest to do this:
// Put an empty array as the initial state.
const [users, setUsers] = useState<User[]>([]);
So if everything succeeds you actually would be updating that empty array to be an array with the response items. and your code would still work.
The code is failing because the state is undefined at first so you're trying to call map on an undefined value.
CodePudding user response:
You have a loading
"state" to guard against attempting to render the items before any data has been fetched, but in useAllUsers
you never actually declared the loading
with a useState
, so in the UserManagement
it will always be false, leading it to attempt to render users
before they are ready.
To fix, you can add the missing loading useState, and I also advise to put an empty array as the initial value of an array type state like so:
const [users, setUsers] = useState<Array<User>>([])