【问题标题】:React router - click on card and redirect to a new page with content of that card (card details) using useParams and reacthooks反应路由器 - 单击卡并使用反应钩子中的 useParams 重定向到包含该卡内容(卡详细信息)的新页面
【发布时间】:2021-08-20 09:01:04
【问题描述】:

我创建了一篇博文。帖子在卡片[Event.js] 中,点击按钮即可。它应该转到新页面并在那里呈现其卡片详细信息。如何使用反应钩子和 useParams 来做到这一点? EventList.js ---> 是我从 api 获取数据的地方 Event.js ---> 我正在将获取的数据呈现在卡片中 EventDetails.js ---> 这是点击帖子时应在屏幕上呈现的卡片详细信息。现在我已经硬编码了。详情。

有人可以帮我解决这个问题吗?

//EventList.js

import React, { useState, useEffect } from "react";
import Event from "../Event/Event";
import axios from "axios";
import styles from "./EventList.module.css";

const EventList = () => {
  const [posts, setPosts] = useState("");

  let config = { Authorization: "..........................." };
  const url = "............................................";

  useEffect(() => {
    AllPosts();
  }, []);

  const AllPosts = () => {
    axios
      .get(`${url}`, { headers: config })

      .then((response) => {
        const allPosts = response.data.articles;
        console.log(response);
        setPosts(allPosts);
      })
      .catch((error) => console.error(`Error: ${error}`));
  };

  return (
    <div>
      <Event className={styles.Posts} posts={posts} />
    </div>
  );
};

export default EventList;

//Event.js

import React from "react";
import styles from "./Event.module.css";
import { Link } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";

const Event = (props) => {
  const displayPosts = (props) => {
    const { posts } = props;

    if (posts.length > 0) {
      return posts.map((post) => {
        return (
          <div>
            <div>
              <div className={styles.post}>
                <img
                  src={post.urlToImage}
                  alt="covid"
                  width="100%"
                  className={styles.img}
                />
                <div>
                  <h3 className={styles.title}>{post.title}</h3>
                  <div className={styles.price}> {post.author} </div>
                  <Link to={`/${post.title}`}>
                    <button className={styles.btns}> {post.author} </button>
                  </Link>
                </div>
              </div>
            </div>
          </div>
        );
      });
    }
  };
  return <div className="Posts">{displayPosts(props)}</div>;
};

export default Event;

//EventDetails.js

import React, { useState, useEffect } from "react";
import Navbar from "../Navbar/Navbar";
import DetailsImage from "../../assets/Event-Ticketing.png";
import styles from "./EventDetails.module.css";
import "bootstrap/dist/css/bootstrap.min.css";
import { Link, useParams, useLocation } from "react-router-dom";
import axios from "axios";

// let config = { Authorization: "3055f8f90fa44bbe8bda05385a20690a" };
// const baseurl = "https://newsapi.org/v2/top-headlines?sources=bbc-news";

const EventDetails = (props) => {
  const { state } = useLocation();

  if (!state) return null;

  // const [title, setTitle] = useState("");

  // const { eventName } = useParams();

  // useEffect(() => {
  //   axios
  //     .get(`${baseurl}`, { headers: config })
  //     .then((response) => setTitle(response.data));
  // }, []);

  // useEffect(() => {
  //   const neweventName = baseurl.find(
  //     (eventNames) => eventNames.eventName === parseInt(eventName)
  //   );
  //   setTitle(neweventName.title);
  // }, []);

  return (
    <div>
      <Navbar />
      <div className={styles.eventBg}>
        <div className="container">
          <div>
            <img
              src={DetailsImage}
              alt="ticket"
              width="100%"
              className={styles.heroEventImage}
            />
          </div>
          <div className={styles.bookingDetails}>
            <div className={styles.nameBook}>
              <div>
                <div className={styles.eventNameHeader}>
                  <h1 className={styles.eventName}> {props.title}</h1>
                </div>
                <div className={styles.genre}>
                  <div className={styles.genreText}>{props.author}</div>
                </div>
              </div>
              <div className={styles.bookingBtn}>
                <div className={styles.booking}>
                  <Link to="/GeneralBooking">
                    <button
                      className={styles.bookBtn}
                      style={{ height: "60px", fontSize: "18px" }}
                    >
                      Book
                    </button>
                  </Link>
                </div>
              </div>
            </div>
            <div className={styles.venueTime}>
              <div className={styles.dateTime}>
                <div className={styles.dateTimeText}>{props.author}</div>
                <div className={styles.price}>{props.author}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default EventDetails;

//App.js

import "./App.css";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Home from "./components/Home/Home";
import EventDetails from "./components/EventDetails/EventDetails";
import GeneralBooking from "./components/GeneralBooking/GeneralBooking";
import AllotedSeated from "./components/AllotedSeated/AllotedSeated";
import Checkout from "./components/Checkout/Checkout";

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <Switch>
          <Route path="/" exact>
            <Home />
          </Route>
          <Route path="/:title" exact children={<EventDetails />}></Route>
          <Route path="/GeneralBooking" exact>
            <GeneralBooking />
          </Route>
        </Switch>

        {/* <EventDetails /> */}
        {/* <GeneralBooking /> */}
        {/* <AllotedSeated /> */}
        {/* <Checkout /> */}
      </div>
    </BrowserRouter>
  );
}

export default App;

【问题讨论】:

  • 您是否将这些组件渲染为特定路径上的RouterEventDetails 需要由 Route 呈现,并且 path 属性需要定义匹配参数才能使 useParams 工作。 posts 状态也应该从一个共同的祖先定位(并传递)。另一种方法是使用路由状态并发送特定的发布数据以及路由转换。
  • 是的,我正在使用 Route 来渲染它。如果需要,我会更新代码。
  • 我已经添加了 App.js

标签: reactjs react-router react-hooks


【解决方案1】:

由于它看起来好像您在 ReactTree 中存储的 posts 状态不够高,无法被其他路由上的组件访问,我建议使用路由状态将特定的 post 对象发送到接收路线。

事件 - 更新 Link 以同时发送 post 对象。

<Link
  to={{
    pathname: `/${post.title}`,
    state: { post },
  }}
>
  <button type="button" className={styles.btns}>{post.author}</button>
</Link>

EventDetails - 使用 useLocation 挂钩访问路由状态。

import { useLocation } from "react-router-dom";

const EventDetails = (props) => {
  const { state } = useLocation();

  if (!state.post) return null;

  return (
    // ...render all the post fields available from state.post
    // i.e. state.post.title
  );
};

【讨论】:

  • 谢谢。我试图渲染帖子 {props.title} 但它的投掷状态未定义?怎么办?
  • 你能告诉我我做错了什么吗?我有点卡住@Drew
  • @sud 是否在if (!state.post) return null; 行上未定义投掷状态?您可以尝试删除 .post 位 (if (!state) return null;) 或为 state (const { state = {} } = useLocation();`) 提供后备。
  • 我试过用你的方法。当我单击卡片时,它会重定向到该特定页面,但内容没有被呈现。我已经更新了问题部分中的 EVentDetails.js 代码,请您查看一下。 @德鲁
  • @Sud 抱歉,我认为它更清晰/明显,但您应该从state.post 而非props 呈现标题、作者等,即state.post.title
猜你喜欢
  • 1970-01-01
  • 2021-06-22
  • 2019-11-25
  • 2014-09-26
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
相关资源
最近更新 更多