I have a question about how to pass a parameter in Link component. I wanna create a page to show a page to edit a quiz users clicked. I could fetch data using getDocs with id in link, but I don't want that because I just only need one data from Firestore depending on the link. The link looks like this
http://localhost:3000/kinniku-quiz/edit/GvsC5GVjDyFtQlBoXjqy
To show the page is fine. When I clicked a small note-look icon, it successfully renders the edit page showing the id. Is there any possible way to pass props, in this case, a quiz, in Link Component??
Here is the page to let users go to the detailed page. Look at the bottom. there is one <Link ...>. When users clicked it, a detailed page will be shown. And I want to pass a quiz at the same time. I can get the id with useParams.
AllQuizzes.jsx
// ========== Import from third parties ==========
import { useState, useEffect } from 'react'
import { collection, onSnapshot } from 'firebase/firestore';
import Loading from 'react-simple-loading';
import { Link } from 'react-router-dom';
// ========== Import from inside this project ==========
import db from '../config/firebase';
import { riEditBoxLine, riDeleteBinLine } from '../icons/icons'
import { handleQuizEdit, handleQuizDelete } from '../hooks/quizCRUD'
// ========== Main ==========
const AllQuizzes = () => {
const [quizzes, setQuizzes] = useState([]);
// useEffect(() => {
// GetAllQuizzes(quiqzzes={quizzes}, setQuizzes={setQuizzes});
// })
useEffect(() => {
const collectionRef = collection(db, 'quizzes');
const unsub = onSnapshot(collectionRef, {
next: snapshot => {
setQuizzes(snapshot.docs.map(doc => ({ ...doc.data(), id: doc.id })));
},
error: err => {
// don't forget error handling! e.g. update component with an error message
console.error('quizes listener failed: ', err);
},
});
return unsub;
// const unsub = onSnapshot(collectionRef, snapshot => {
// setQuizzes(snapshot.docs.map(doc => ({ ...doc.data(), id: doc.id })));
// });
// return unsub;
// getData(): run once
// onSnapshot(): listen for realtime updates
}, []);
return (
<div className="allQuizzes">
{quizzes.length === 0 ? <Loading color={"#005bbb"} /> : ""}
{quizzes.map((quiz, quizIndex) => (
<div className="eachQuizContainer" key={quiz.id}>
<div className="quizQuestionContainer">
<span className="quizIndex">{quizIndex 1}.</span>
<p className="quizQuestion">{quiz.question}</p>
</div>
<div className="icons">
<Link to={{pathname: `/kinniku-quiz/edit/${quiz.id}`, query: {quiz: quiz}}}><i className="riEditBoxLine" onClick={() => handleQuizEdit(quiz.id)}>{riEditBoxLine}</i></Link>
<i className="riDeleteBinLine" onClick={() => handleQuizDelete(quiz.id)}>{riDeleteBinLine}</i>
</div>
</div>
))}
</div>
)
};
export default AllQuizzes;
I also tried this, neither did it.
<Link to={{pathname: `/kinniku-quiz/edit/${quiz.id}`}} q={quiz}><i className="riEditBoxLine" onClick={() => handleQuizEdit(quiz.id)}>{riEditBoxLine}</i></Link>
QuizEdit.jsx
I can see the id on the page, but no quiz props.
import { useParams } from 'react-router-dom';
import { collection, query, where, getDocs } from 'firebase/firestore';
import db from '../config/firebase';
const QuizEdit = ({quiz}) => {
const { id } = useParams();
console.log(quiz)
return (
<div>
<h3>{id}</h3>
<p>{quiz}</p>
</div>
);
};
export default QuizEdit;
App.js
// Import from 3rd parties
import { BrowserRouter, Routes, Route } from 'react-router-dom';
// Import files existing in this project
import './styles/Style.css';
import './styles/quiz.css';
import Header from "./components/Header";
import Footer from "./components/Footer";
import Test from "./components/Test";
import Home from "./components/Home";
import QuizEdit from "./components/QuizEdit";
// import About from "./components/About";
import ErrorPage from "./components/ErrorPage";
import Profile from "./components/Profile";
import QuizHome from "./components/QuizHome";
import QuizSelect from "./components/QuizSelect";
import AllQuizzes from "./components/AllQuizzes";
import FormikNewQuiz from "./components/FormikNewQuiz";
// Actual Coding
function App() {
return (
<BrowserRouter>
<Header />
<div id="main">
<Routes>
<Route path="/" element={<Home />} />
{/* <Route path="about" element={<About />}/> */}
<Route path="kinniku-quiz/" element={<QuizHome />}>
<Route path="new" element={<FormikNewQuiz />} />
<Route path="test" element={<Test />} />
<Route path="all-quizzes" element={<AllQuizzes />} />
<Route path="edit/:id" element={<QuizEdit />} />
</Route>
<Route path="profile/:userId" element={<Profile />} />
<Route path="*" element={<ErrorPage />} />
</Routes>
</div>
<Footer />
</BrowserRouter>
);
}
export default App;
Thanks for your valuable time in advance.
CodePudding user response:
It looks like you are either forgetting to use Route
, Routes
, or BrowserRouter
. I cannot really tell due to the lack of a minimal working example. Here is a version where the routing is working and a prop called quiz is being passed to QuizEdit when your url is selected (using the Link provided).
Edit
It looks like in your line
<Route path="edit/:id" element={<QuizEdit />} />
You aren't actually passing props called quiz to it.
To do this you can do:
<Route path="edit/:id" element={<QuizEdit quiz={"quiz props!"} />} />
const QuizEdit = ({quiz}) => {
const { id } = ReactRouterDOM.useParams();
console.log(quiz, id)
return (
<div>
<h3>{id}</h3>
<p>{quiz}</p>
</div>
);
};
const App = () => {
return (
<div>
<ReactRouterDOM.Link to="/kinniku-quiz/edit/GvsC5GVjDyFtQlBoXjqy">
Go to your URL
</ReactRouterDOM.Link>
<ReactRouterDOM.Routes>
<ReactRouterDOM.Route path="/kinniku-quiz/edit/:id" element={<QuizEdit quiz="quiz stuff" />} />
<ReactRouterDOM.Route path="*" element={<p>This will render on any path that is not the one specified in your question</p>} />
</ReactRouterDOM.Routes>
</div>
)
}
ReactDOM.render(
<ReactRouterDOM.BrowserRouter>
<App />
</ReactRouterDOM.BrowserRouter>,
document.getElementById("app")
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- Load history -->
<script src="https://unpkg.com/history@5/umd/history.development.js" crossorigin></script>
<!-- Load React Router and React Router DOM -->
<script src="https://unpkg.com/react-router@6/umd/react-router.development.js" crossorigin></script>
<script src="https://unpkg.com/react-router-dom@6/umd/react-router-dom.development.js" crossorigin></script>
<div id="app"></div>
CodePudding user response:
If you have or want to have a view page and an edit page both having id
parameters then have two routes ie
- Edit
<Link to="your_paths/edit/:id">Edit </Link>
- Just view
<Link to="your_paths/view/:id>View </Link>
- Delete
<Button onClick={e=>handleDelete(id)}>Delete</Button>