skip to Main Content

How can I link to the corresponding child React component using Link from react-router-dom? By passing an id to the url. Now I’m getting the id, but the component isn’t rendered.

https://codesandbox.io/s/test-login-page-tasks-rmfn5j?file=/src/components/Taskslist.js

Parent component

const ParentComponent = ({ Tasks }) => {
  const params = useParams();
  const id = params.id; 

  return (
    <div className="wrapper">
      {Tasks.map((task) => (
        <div key={id}>
          <h3>{task.title}</h3>
          <h4>{task.author_name}</h4>
        </div>
      ))}
    </div>
  );
};

Child component

Import Link from react-router-dom

<Link to="/task/:id">
    <Task       
       goToTask={goToTask}
    />
</Link>

I’m trying to render the child component when clicking on its link at the Parent component list. So the url changes, but the Child component isn’t rendered and the window is empty. Maybe it’s not good using at the same time Link and useParams. I’m trying to get the child component id and pass so I can link to the specific child component.

2

Answers


  1. You have a small typo in your router code. the code you have for the task id is

     <Route path="task/:id">
       <TaskComponent Tasks={tasks} />
     </Route>
    

    should be modified to this

     <Route path="/task/:id">
       <TaskComponent Tasks={tasks} />
     </Route>
    

    you forgot the slash /
    after that it should work fine.
    what you will have after modification

    Login or Signup to reply.
  2. The code is rendering links to the literal path "/task/:id" instead of "injecting" the task id value in to the target path.

    TaskList

    Instead of wrapping an array of filtered tasks by status, filter then map each array of tasks to a link to the specific task.

    import { useHistory } from "react-router-dom";
    
    const Taskslist = ({ Tasks }) => {
      const history = useHistory();
    
      const newtask = () => {
        history.push("/newtask");
      };
    
      return (
        <div className="wrapper">
          <h1>Tasks</h1>
          <button onClick={newtask}>New Task</button>
          <div className="tasks__wrapper">
            <div className="tasks__tasks-item">
              <h2>In queue</h2>
              {Tasks
                .filter((task) => task.status === 0)
                .map(task => <Task tasks={task} />)
              }
            </div>
            <div className="tasks__tasks-item">
              <h2>In progress</h2>
              {Tasks
                .filter((task) => task.status === 1)
                .map(task => <Task tasks={task} />)
              }
            </div>
            <div className="tasks__tasks-item">
              <h2>Completed</h2>
              {Tasks
                .filter((task) => task.status === 2)
                .map(task => <Task tasks={task} />)
              }
            </div>
          </div>
          <button>Back</button>
        </div>
      );
    };
    

    Task

    import React from "react";
    import { Link, generatePath } from "react-router-dom";
    
    const Task = ({ task }) => {
      return (
        <div className="wrapper">
          <Link to={generatePath("/task/:id", { id: task.id })}>
            <h3>{task.title}</h3>
            <h4>{task.author_name}</h4>
          </Link>
        </div>
      );
    };
    
    export default Task;
    

    TaskComponent

    const TaskComponent = ({ Tasks }) => {
      const { id } = useParams();
    
      const task = Tasks.find(task => String(task.id) === id);
    
      if (!task) {
        // no task, render fallback UI
        return <div>No Task</div>;
      }
    
      return (
        <div className="wrapper">
          <div>
            <h3>{task.title}</h3>
            <h4>{task.author_name}</h4>
          </div>
        </div>
      );
    };
    

    App – the route being linked to is missing the leading "/" character.

    function App() {
      const [tasks, setTasks] = useState(Tasks);
      return (
        <BrowserRouter>
          <div>
            <Header />
            <Switch>
              <Route path="/" exact={true}>
                <Login authors={Authors} />
              </Route>
              <Route path="/taskslist">
                <Taskslist Tasks={tasks} />
              </Route>
              <Route path="/newtask">
                <NewTask
                  authors={Authors}
                  onFinish={(newTask) => {
                    setTasks((pre) => [
                      ...pre,
                      { ...newTask, id: Math.random().toString() }
                    ]);
                  }}
                />
              </Route>
              <Route path="/errorlogin">
                <ErrorLogin />
              </Route>
              <Route path="/task/:id">
                <TaskComponent Tasks={tasks} />
              </Route>
            </Switch>
          </div>
        </BrowserRouter>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search