ROUTES
<Routes>
<Route
exact
path="/"
element={
<div>
<BlogForm />
<BlogList />
</div>
}
/>
<Route path="/blogs" element={<UserList />} />
<Route path="/users" element={<UserList />} />
<Route path="/users/:id" element={<User />} />
<Route path="/blogs/:id" element={<BlogSingle />} />
</Routes>
Here I have all my routes. All of them works except the last one '/blogs/:id' which renders <BlogSingle />
. It throws an uncaught type error from my <Blog/>
component which is rendered inside <BlogList />.
I have my <Link>
components in <Blog/>
but I don't think that's the cause of the problem since I tried deleting it and going to /blogs/:id manually. Why does my last Route re-renders the <Blog/>
component. Any thoughts?
BLOGLIST
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { initializeBlogs } from '../reducers/blogReducer'
import Blog from './Blog'
const BlogList = () => {
const dispatch = useDispatch()
const user = useSelector(({ login }) => {
return login
})
useEffect(() => {
dispatch(initializeBlogs())
}, [dispatch])
const blogs = useSelector(({ blog }) => {
return blog
})
return (
<div>
{blogs.map((blog) => (
<Blog key={blog.id} user={user} blog={blog}></Blog>
))}
</div>
)
}
export default BlogList
BLOG
[import { useState } from 'react'
import { useDispatch } from 'react-redux'
import { saveLikes, deleteBlog } from '../reducers/blogReducer'
import { Link } from 'react-router-dom'
const Blog = ({ user, blog }) => {
const \[visualForm, setVisualForm\] = useState(true)
const dispatch = useDispatch()
const longFormVisible = { display: visualForm ? 'none' : '' }
const shortFormVisible = { display: visualForm ? '' : 'none' }
const toggleForm = () => {
setVisualForm(!visualForm)
}
const showDelete = blog.user.id.toString() === user\[0\].id.toString()
const blogStyle = {
paddingTop: 10,
paddingLeft: 2,
border: 'solid',
borderWidth: 1,
marginBottom: 5,
}
return (
<div>
<div style={Object.assign({}, blogStyle, longFormVisible)}>
{blog.title} {blog.author}
<button type="submit" onClick={toggleForm}>
hide
</button>
<br />
{blog.url}
<br />
likes: {blog.likes}{' '}
<button type="submit" onClick={() => dispatch(saveLikes(blog))}>
like
</button>
<br />
{blog.user.name}
<br />
{showDelete ? (
<button type="submit" onClick={() => dispatch(deleteBlog(blog))}>
delete
</button>
) : (
''
)}
</div>
<div style={Object.assign({}, blogStyle, shortFormVisible)}>
<Link to={`blogs/${blog.id}`}>
{blog.title} {blog.author}
</Link>
<button type="submit" onClick={toggleForm}>
view
</button>
</div>
</div>
)
}
export default Blog][1]
BLOGSINGLE
import { useMatch } from 'react-router-dom'
import { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { initializeUsers } from '../reducers/userReducer'
import { initializeBlogs } from '../reducers/blogReducer'
const BlogSingle = () => {
const dispatch = useDispatch()
useEffect(() => {
dispatch(initializeUsers())
}, [dispatch])
useEffect(() => {
dispatch(initializeBlogs())
}, [dispatch])
/*const users = useSelector(({ user }) => {
return user
})*/
const blogs = useSelector(({ blog }) => {
return blog
})
const match = useMatch('/blogs/:id')
const blog = match
? blogs.find((blog) => blog.id === match.params.id.toString())
: null
console.log(match.params.id.toString())
if (!blog) {
return null
}
return (
<div>
<h1>
{blog.title} {blog.author}
</h1>
<h2>added blogs</h2>
</div>
)
}
export default BlogSingle
Route below also works. I used <UserList />
just to try. I actually don't have a view for /blogs url. Only 'blogs/:id'.
<Route path="/blogs" element={<UserList />} />
I added the error in the link.
/localhost:xxxx/blogs/62965dbc5553186f396413ac when I go to this URL I get this error. ERROR
Uncaught TypeError: Cannot read properties of undefined (reading 'user') at Blog (bundle.js:142:27) at renderWithHooks (bundle.js:36135:22) at mountIndeterminateComponent (bundle.js:40752:17) at beginWork (bundle.js:42207:20) at HTMLUnknownElement.callCallback (bundle.js:24059:18) at Object.invokeGuardedCallbackDev (bundle.js:24108:20) at invokeGuardedCallback (bundle.js:24170:35) at beginWork$1 (bundle.js:47132:11) at performUnitOfWork (bundle.js:46269:16) at workLoopSync (bundle.js:46182:9)
Thanks in advance.
CodePudding user response:
The router code you've pasted has
<Route path="/blogs" element={<UserList />} />
<Route path="/users" element={<UserList />} />
Presumably, the first element should be <BlogList />
– that should prevent it from trying to render a different component.'
Additionally, the order of routes within <Routes>
matters:
<Route path="/users/:id" element={<User />} />
<Route path="/blogs/:id" element={<BlogSingle />} />
<Route path="/blogs" element={<BlogList />} />
<Route path="/users" element={<UserList />} />
should do the trick.
CodePudding user response:
I'm just an idiot. I accidentally imported BlogSingle as 'import BlogSingle from './Blog'' instead of './BlogSingle'. It is now working.