I am working on react and routing a few links in App.js, of which 2 have an :id parameter as seen below
import React from "react";
import "./App.css";
import { BrowserRouter as Route, Switch } from "react-router-dom";
import Home from "./Components/Home";
import NavBar from "./Components/NavBar";
import About from "./Components/About";
import Contact from "./Components/Contact";
import CatsList from "./Pages/CatsList";
import CatsUpdate from "./Pages/CatsUpdate";
import CatsCreate from "./Pages/CatsCreate";
import AuthCatShow from "./Pages/AuthCatShow";
import CatShow from "./Pages/CatShow";
function App() {
return (
<div className="App">
<NavBar />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/contact">
<Contact />
</Route>
<Route path="/cats/:id">
<AuthCatShow />
</Route>
<Route path="/cats/list">
<CatsList />
</Route>
<Route path="/cats/new">
<CatsCreate />
</Route>
<Route path="/cats/edit/:id">
<CatsUpdate />
</Route>
</Switch>
</div>
);
}
export default App;
Note the components with cat/:id and cat/edit/:id requires the id params. I tried using use params in them, but it doesn't work. For example, for cats/:id, I did:
let id = useParams();
and then I should be able to access the id like so: id.id
(It was working a few days before!)
import axios from "axios";
import React, { useEffect, useState } from "react";
import { BrowserRouter as Link, useParams } from "react-router-dom";
import styled from "styled-components";
const LinkStyled = styled(Link)`
text-decoration: none;
color: black;
`;
const Img = styled.img`
border-radius: 50%;
`;
function AuthCatShow() {
let id = useParams();
console.log(id);
// For the cat data
const [cat, setCat] = useState();
const [toggle, setToggle] = useState(false);
// handle function for adding comment
const handleComment = (event) => {
event.preventDefault();
setToggle(!toggle);
let text = event.target[0].value;
let cat_id = id.id;
let user_id = id.id;
let email = id.id;
const payload = { text, cat_id, user_id, email };
axios
.post(`http://localhost:3000/api/cats/${id.id}/newcomment`, payload)
.then((res) => {
window.alert(`Comment added!`);
});
};
// handle function for updating comment
const updateComment = async (id) => {
setToggle(!toggle);
let updateCommentText = prompt("Update the comment:");
await axios
.put(`http://localhost:3000/api/comments/${id}`, {
text: updateCommentText,
})
.then((res) => {
window.alert(`Comment updated!`);
});
};
// handle function for deleting comment
const deleteComment = (id) => {
setToggle(!toggle);
axios.delete(`http://localhost:3000/api/comments/${id}`);
};
// useeffect to get the cats data
useEffect(() => {
async function getCatData() {
await axios.get(`http://localhost:3000/api/cats/${id.id}`).then((cat) => {
setCat(cat.data.data);
});
}
getCatData();
}, [updateComment]);
return (
<>
<div>
<h1>{cat?.name}</h1>
<Img src={cat?.image} alt={cat?.name} width="400px" height="400px" />
<p>Description: {cat?.description}</p>
<p>Gender: {cat?.gender}</p>
<p>Adoptable: {cat?.adoptable}</p>
<p>Cage: {cat?.cage}</p>
<button>
<LinkStyled to={`/cats/list`}> Back </LinkStyled>
</button>
</div>
<div>
<h3>Comments</h3>
{cat?.comments?.map((element) => {
return (
<>
<p key={element._id}>
<p>
{element.text}
<button onClick={() => updateComment(element._id)}>
✎
</button>
<button onClick={() => deleteComment(element._id)}>
🗑
</button>
</p>
<br />
<p>Posted by: {element.email}</p>
</p>
</>
);
})}
<form onSubmit={handleComment}>
<input type="text" minLength="3" />
<button>Add comment</button>
</form>
</div>
</>
);
}
export default AuthCatShow;
However, now, id.id doesn't work. For reference, when I console.log id, I get an object with many properties inside like this:
I am really confused. Why is this the case? It was working a few days ago, and it was an object with just 1 property inside, allowing me to use "id.id" in my code. Any help would be appreciated!
CodePudding user response:
You can't use BrowserRouter as Route inside Switch . BrowserRouter has to be used outside of Switch . It should be like this .
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
function App() {
return (
<div className="App">
<Router>
<Switch>
<Route path="/cats/:id">
<AuthCatShow />
</Route>
</Switch>
</Router>
</div>
);
}
export default App;
Try to use like this. It may work.
CodePudding user response:
Honestly I don't really know what happened but thank you for all your comments! There was some routing issue and I didn't change anything in the component, I simply edited the routes in App.js like so:
import React from "react";
import "./App.css";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Home from "./Components/Home";
import NavBar from "./Components/NavBar";
import About from "./Components/About";
import Contact from "./Components/Contact";
import CatsList from "./Pages/CatsList";
import CatsUpdate from "./Pages/CatsUpdate";
import CatsCreate from "./Pages/CatsCreate";
import AuthCatShow from "./Pages/AuthCatShow";
import CatShow from "./Pages/CatShow";
function App() {
return (
<div className="App">
<Router>
<NavBar />
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/contact">
<Contact />
</Route>
<Switch>
<Route path="/cats/list">
<CatsList />
</Route>
<Route path="/cats/new">
<CatsCreate />
</Route>
<Route path="/cats/edit/:id">
<CatsUpdate />
</Route>
<Route path="/cats/:id">
<AuthCatShow />
</Route>
</Switch>
</Router>
</div>
);
}
export default App;
And now the useParams work!