繁体   English   中英

将查询从搜索栏传递到结果页面 React

[英]Pass query from Search bar to results page React

我制作了一个搜索和过滤栏,作为我在 React 中制作的应用程序的一部分。 当前的工作方式是在您键入时显示建议。 但是,如果用户只是单击提交按钮,则没有处理程序。 现在单击提交按钮将带您到一个结果页面,其中包含页面 URL 中的查询。我希望在您单击该链接时将其作为 state 传递。 然后可以在结果组件中显示该链接。 我尝试过这个,但我对 React 还很陌生,所以我们将不胜感激。

这是搜索组件:

import * as React from 'react';
import { useState } from "react";
import { Link } from "react-router-dom";

const content = [
    {link: '/review/elden-ring', name: 'Elden\nRing'},
    {link: '/review/', name: 'defg'},
    {link: '/review/', name: 'ghij'},
    {link: '/review/', name: 'jklm'},
]

export default function Search(props) {
    //For storing and setting search input
    const [query, setQuery] = useState("");

    return (
        //Search input
        <div class="flex flex-col z-10">
            <form class="text-black ml-5 py-0.5 lg:py-0 flex border-2 border-gray-400 rounded-md bg-white px-1">
                <input id="searchInput" class="focus:outline-none" type="text" placeholder="Search" value={query} onChange={event => {setQuery(event.target.value)}}/>
                
                <div class="flex mt-1.5"> {/* Flex container to align the icon and bar */}
                    <Link to={{pathname: "/results/" + query, state: {query}}}> {/* Error handler as search is strick */}
                        <button type="submit" onClick={() => setQuery(() => "")}>
                            <svg class="fill-current h-auto w-4 " xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> {/* ! Font Awesome Pro 6.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. */}
                            <path d="M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z" />
                            </svg>
                        </button>
                    </Link>
                </div>
            </form>

            {/* Search Suggestions */}
            <div class="ml-5 px-0.5">
                {/* Query must have length to prevent mapping by default */}
                {query.length > 0 && content.filter((content) => {
                    //If input return object
                    if (query == "") {
                        return content
                    }

                    //If any input characters much object characters return corresponding object
                    else if (content.name.toLowerCase().includes(query.toLocaleLowerCase())) {
                        return content
                    }

                })
                //Maps element based on the number of json objects
                .map((content) => {
                    return(
                        <div class="bg-white rounded-sm">
                            <Link to={content.link} onClick={() => setQuery(() => "")}><p>{content.name}</p></Link>
                        </div>
                    );
                })};
            </div>
        </div>
    );
};

这是结果组件

import *  as React from 'react';

export default function Results(props) {
    return (
        <h1>{props.location.state.query}</h1>
    );
};

航线

import * as React from 'react';
import './app.css';
import { Routes, Route } from "react-router-dom";

import Header from './components/header/header';
import Footer from './components/footer';
import Error from './components/error';
import Results from './components/results';
import Index from './components/index/index';
import ReviewsPage from './components/reviews/reviewsPage';
import Review from './components/reviews/review';

export default function App() {
  return (
    <>
      <Header />
      
      <Routes>
        <Route path="/" element={<Index />} />
        <Route path="/reviews" element={<ReviewsPage />} />
        {/* Render review with ID for switch statment */}
        <Route path="/review/:id" element={<Review />} />
        <Route path="/results/:id" element={<Results />} />
        <Route path="*" element={<Error />} />
      </Routes>

      <Footer />
    </>
  );
};

搜索组件导入第30行

import * as React from 'react';
import Search from './search';
import { useState } from 'react';
import { Link } from 'react-router-dom';

export default function Header() {
  //State to toggle navlinks on small screens
  const [state, setState] = useState(false)

  return (
    <nav className=" w-full bg-red-500 shadow-lg relative max-h-[4.1rem]"> {/* Max height set to avoid search suggestions increasing header size */}
      <div className="flex justify-between py-3.5 w-full px-3 md:w-2/3 md:px-0  m-auto">
        {/* Logo */}
        <Link className="text-2xl font-semibold text-white hover:animate-pulse whitespace-nowrap"  to="/">GAME REVIEWS</Link>

        <div className="flex max-h-[3rem]"> {/* Container to prevent flex effecting both parents container */}
          {/* Links */}
          {!state && (
            <ul id="links" className=" h-40 lg:h-auto flex-col flex lg:flex-row absolute lg:relative mt-10 lg:mt-0 right-0 lg:right-auto px-10 lg:px-0 bg-red-500 rounded-lg lg:rounded-none shadow-sm lg:shadow-none">
              <li className="m-5 lg:my-0 lg:mx-5">
                <Link className="text-2xl text-white border-none hover:border-solid border-b-2 border-white" to="/">Home</Link>
              </li>
              <li className="m-5 lg:my-0 lg:mx-5">
                <Link className="text-2xl text-white border-none hover:border-solid border-b-2 border-white" to="/reviews">Reviews</Link>
              </li>
            </ul>
          )}

          {/* Search bar */}
          <Search />

          {/* Hamburger */}
          <div id="hamburger" onClick={() => setState(!state)} className=" space-y-2 ml-5 mt-2 block cursor-pointer lg:hidden">
            <div className="w-6 h-0.5 bg-white"></div>
            <div className="w-6 h-0.5 bg-white"></div>
            <div className="w-6 h-0.5 bg-white"></div>
          </div>
        </div>
      </div>
    </nav>
  )
}

这是我想要实现的用户搜索“游戏”的示例

在此处输入图像描述

单击右侧的图标后,他们应该被重定向到我的结果页面。 此页面应显示他们刚刚在提交时输入的内容。

在此处输入图像描述

如果您希望共享页面结果,则必须在 url 中包含搜索词,例如: www.yourdomain.com/review/elden-ring

看一看,您会发现我已经定义了review路线现在需要一个参数。 您应该使用该参数来检查您需要在页面上显示的所有数据。

并且必须编辑搜索组件,因为您使用class而不是className进行样式设置。

Results组件上,我使用useParams挂钩获取 url 参数并将其显示在h1上。 您应该使用此参数作为键来检索您的 API 评论的实际详细信息。

这就是我要做的(所有逻辑):

在 App 组件上,我定义了路由:

<Routes>
        <Route exact path="/" element={<Search />} />
        <Route path="/review/:query" element={<Results />} />
      </Routes>

在搜索组件上:

// Router v6 hook to navigate the user
const navigate = useNavigate();

const queryRef = useRef(null) // Reference to the input

// Navigates the user to reviews/what they've written 
const queryHandler = () => navigate(`/reviews/${queryRef.current.value}`);

return (
<>
   // This is where the user types the query
   <input type='text' ref={queryRef} placeholder='Search' />
   <Icon onClick={queryHandler} /> // This has the onClick to hndle the click
</>
)

在结果组件上:

const params = useParams(); // This retrieves all the params defined for the url 

<h1>{params.query}</h1>

您可以在 URL 中传递queryLink组件中使用动态路由。要在Result组件中解析它,您可以使用match道具。

要导航,请将您的Link组件更改为

<Link to={"/results/" + query} />

并解析Result组件中的query ,使用

<h1>{props.match.params.id}</>

您在history.push()方法中发送的query必须是object 相反,您发送的是一个字符串。 如下所示将其更改为 object

    props.history.push({
       pathname: '/results',
       state: { query }
    });

对于以下路线。 本地主机:3000/搜索/?查询= ABCD

以下加载代码从 query=ABCD 中提取 ABCD 并设置为 state。


export default function App() {
  const [query, setQuery] = useState(() => {
    const q = new URLSearchParams(window.location.search);
    console.log(q.toString());
    return q.get("query") || "";
  });

  return (
    <div className="App">
      <h1>Query</h1>
      <h2>{query}</h2>
    </div>
  );
}

因此,您可以通过这种方式从路线中提取信息。

现在如果你想知道如何从一页移动到另一页

假设您正在使用一些路由库,看看如何更改路由

history.push(`/search/?query={query}`)

是一种与反应路由器一起使用的方法(确保你使用 useHistory 钩子)

它比我想象的要简单得多,而且我在另一个页面上做了一些事情

为输入创建一个 state。 将输入设置为 state(查询)中的变量。 使用按钮上的 onClick 将值设置为输入。 然后该链接提供了带有路由的 state 变量。

const [query, setQuery] = useState("");

      <form
        className="text-black ml-5 py-0.5 lg:py-0 flex border-2 border-gray-400 rounded-md bg-white px-1"
      >
        <input
          id="searchInput"
          className="focus:outline-none"
          type="text"
          placeholder="Search"
          value={query}
          onChange={(event) => {
            setQuery(event.target.value);
          }}
        />

        {/* Flex container to align the icon and bar */}
        <div className="flex mt-1.5">
          <Link to={{ pathname: "/results/" + query }}>
            <button type="submit" onClick={() => setQuery(() => "")}>
              <svg
                className="fill-current h-auto w-4 "
                xmlns="http://www.w3.org/2000/svg"
                viewBox="0 0 512 512"
              >
                {/* ! Font Awesome Pro 6.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. */}
                <path d="M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z" />
              </svg>
            </button>
          </Link>
        </div>
      </form>

然后在路由中路径被赋予一个变量(id)

<Route path="/results/:id" element={<Results />} />

然后可以通过 useParams 将其拉入结果页面。 并分配给我的 h1 标签。

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

export default function Results(props) {
    const {id} = useParams();

    return (
        <h1>{id}</h1>
    );
};

感谢大家的帮助和指导。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM