The app displays all photos <Photo> in a grid <PhotoGrid>, then once clicked, a function in <Photo> changes URL with history.push, and Router renders <Single> based on URL using useParams hook.
PhotoGrid -> Photo (changes URL onClick) -> Single based on URL (useParams).
I must have messed something up, becouse useParams returns undefined.
Thanks for all ideas in advanced. App.js
class App extends Component {
render() {
return (
<>
<Switch>
<Route exact path="/" component={PhotoGrid}/>
<Route path="/view/:postId" component={Single}/>
</Switch>
</>
)
}
}
export default App;
Photogrid.js
export default function PhotoGrid() {
const posts = useSelector(selectPosts);
return (
<div>
hi
{/* {console.log(posts)} */}
{posts.map((post, i) => <Photo key={i} i={i} post={post} />)}
</div>
)
}
in Photo I change URL with history.push
const selectPost = () => {
(...)
history.push(`/view/${post.code}`);
};
Single.js
import { useParams } from "react-router-dom";
export default function Single() {
let { id } = useParams();
console.log("id:", id) //returns undefined
return (
<div className="single-photo">
the id is: {id} //renders nothing
</div>
)
}
When using useParams, you have to match the destructure let { postId } = useParams(); to your path "/view/:postId".
Working Single.js
import { useParams } from "react-router-dom";
export default function Single() {
const { postId } = useParams();
console.log("this.context:", postId )
return (
<div className="single-photo">
{/* render something based on postId */}
</div>
)
}
You should use the same destructure as mentioned in your Route path. In this case, you should have written :
let { postID } = useParams();
I will mention two more mistakes which someone could make and face the same problem:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With