I running circles with this one. Thanks in advance for all the help you could provide.
The issue is whith the way of accessing a view for a single item in an array. The id param is passed in the address and accessed with useMatch() from react-router-dom. (Edit: example bellow also shows code with the use of useParams as I tried to follow other user's use cases)
The id from the match.params seems the same as one of the items' array (as it should be) Unfortunately, running array.find() doesn't end with a positive result, rather an undefined value.
I searched the web for details on this and maybe this is to do with v6 of the React Router ?
Doing the final exercice of the full-stack-open part 7: https://fullstackopen.com/en/part7/exercises_extending_the_bloglist#exercises-7-9-7-21
I finally ended up asking AI for debbugging but it made me check for everything I already did.
Here is the code from the Component :
{[...users].map(u =>
<tr key={u.id}>
<td><Link to={`/users/${u.id}`}>{u.id}</Link></td>
<td>{u.blogs.length}</td>
</tr>
)}
Here is the App.jsx (wrapped in main.jsx by BrowserRouter) :
import { Routes, Route, Link, useParams } from 'react-router-dom'
const App = () => {
useEffect(() => {
userService.getAll()
.then(users => {
setUserList(users)
console.log('UserList:', users) // Verify the structure and content of userList
})
.catch(error => console.error('Error fetching users:', error))
}, [])
// With useMatch() //////
const userMatch = useMatch('/users/:id')
console.log('userMatch id: ', String(userMatch.params.id))
console.log('userList id: ', String(userList[0].id))
const u = userMatch && userList > 0
? userList.find(u => String(u.id) === String(userMatch.params.id))
: null
console.log('User found:', u) // Log the found user
// With useParams() ////////////
let { id } = useParams() // Get the id parameter directly
console.log('Params ID:', id) // Log the id parameter
console.log('UserList:', userList) // Log the userList contents
const u = userList.length > 0
? userList.find((u) => {
console.log('Checking user:', u.id, 'with ID:', id) // Log the comparison
return Number(u.id) === Number(id)
})
: null
console.log('User found:', u) // Log the found user
return (
<div>
<div>
<Link to='/'>Home</Link>
<Link to='/users'>Users</Link>
</div>
<div>
<h2>blogs</h2>
<Notification notification={notification} />
<div>
{users.name} logged in
<button onClick={handleLogout}>
logout
</button>
</div>
<Routes>
<Route path='/users/:id' element={<User user={u} />} />
<Route path='/users' element={<Users users={userList} />} />
<Route path='/' element={<Home />} />
</Routes>
</div>
</div>
)
Those tests were done and ok-ed :
Verify Router Setup:
Ensure that BrowserRouter
(or HashRouter
) is correctly wrapping your App
component in the root file (index.js
or equivalent):
Check URL and Routing Configuration:
Ensure the URL matches the route pattern defined in your Routes
. For example, if the route is "/users/:id"
, the URL should be something like http://localhost:3000/users/1
.
Test useParams
in Isolation:
Simplify the component to directly test useParams
and see if it correctly extracts the id
:
Simplify App
for Debugging:
Create a minimal version of App
just to test routing:
Check userList
Contents:
If useParams
correctly extracts the id
, then the issue might lie in how userList
is being populated or accessed.
Cross-Verify user.id
Type:
Ensure that user.id
in userList
matches the type of id
extracted from useParams
.
So... TLDR: redid the project from the working logic
I started again from the sandbox code made by Drew Reese from my project: https://codesandbox.io/p/sandbox/busy-water-2rpdcz
After moving components to their own files and adding the backend import for the userList, it still worked and I am now able to complete the exercice.
I am still puzzled to this day at what was the issue with my previous code.