Home > database >  how to pass parameter in Link Component
how to pass parameter in Link Component

Time:03-27

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

  1. Edit <Link to="your_paths/edit/:id">Edit </Link>
  2. Just view <Link to="your_paths/view/:id>View </Link>
  3. Delete <Button onClick={e=>handleDelete(id)}>Delete</Button>
  • Related