【问题标题】:React Router & Link: It does not respect search parameters (or so I think)React Router & Link:它不尊重搜索参数(或者我认为)
【发布时间】:2021-10-01 11:33:41
【问题描述】:

我正在创建自己的迷你博客,并正在实现搜索功能。

我使用 Strapi,一个无头 CMS。因此,如果我想搜索特定帖子,我可以在 API 调用中添加 ?_q=search here 以查询这些帖子。

在我的 React 应用程序中,我有一个 Posts 组件,它将页面中的 URL 转发到 API,这可以通过 window.location.pathname + window.location.search 轻松完成。因此,如果有人访问https://exampleblog.com/posts?_q=search here,那么 React 将获取路径名和搜索参数并将其用于对 Strapi 的 API 调用。我这样做是因为它可以节省很多工作。

借助我的搜索功能,我使用来自react-router-domLink 组件作为搜索按钮。有一个状态从文本框中获取值,并更改Link 组件中to 属性的值,使to 看起来像/posts?_q=textbox value。并且由于页面中的路径名和搜索参数被转发到 API,它应该会解析正确的帖子。

我的问题是,如果 URL 中的路径名发生变化(例如 /posts 变为类似 /categories),Link 组件会呈现页面(这是正确的)。 但是,如果只有search 参数发生变化(URL 中的?_q=search here),那么浏览器中的 URL 会发生变化,但不会呈现任何新内容。

我还想补充一点,当从具有不同路径名的页面进行搜索时,搜索 100% 有效,因此搜索参数是有效的。但是,如果我在具有相同路径名的页面上执行搜索,则不会。

根据我的观察,我得出的结论是Link 组件不考虑对 URL 中搜索参数的更改。

下面是一些示例代码。

来自Posts 组件的片段:

const pathname = window.location.pathname + window.location.search;
const {loading, error, data} = useApi(pathname); // Custom hook to resolve API requests. Already knows the hostname.
// Continued code in this component will render the API result

Search 组件的整体:

import React, {useState} from 'react';
import {Link} from 'react-router-dom';

export default function Search() {
    const [query, setQuery] = useState('');

    return (
        <div className="search">
            <label>Search</label>
            <input type="text" onChange={event => setQuery(event.target.value)}></input>
            <Link to={`/posts?_q=${query}`} className="button">
                Search
            </Link>
        </div>
    );
}

我的“useApi”自定义钩子:

export default function useApi(endpoint = '/') {
    const URI = process.env.URI;

    const [state, setState] = useState({
        loading: true,
        error: false,
        data: null
    });

    useEffect(() => {
        (async () => {
            try {
                const response = await axios.get(URI + endpoint);
                const data = response.data;

                setState({
                    loading: false,
                    error: false,
                    data
                });
            } catch (error) {
                setState({
                    loading: false,
                    error: true,
                    data: null
                });
            }
        })();
    }, [endpoint]);

    return state;
}

如您所见,提供给 useApi 钩子的端点参数最终将是window.location.pathname + window.location.search,这意味着它将跟踪必要的更改,包括搜索参数的更改值。

如往常一样,任何帮助将不胜感激。

【问题讨论】:

    标签: javascript reactjs hyperlink react-router-dom


    【解决方案1】:

    问题: 当查询参数发生变化时,组件不会重新渲染,因此不会再次调用 API。

    解决方案: 您应该在 useEffect() 挂钩中使用依赖数组中的查询参数调用 API,以便每当查询参数更改时,都会使用新的查询参数调用 API。

    【讨论】:

    • 您好 Zohaib,非常感谢您的回复。我已经在依赖数组中跟踪了正确的值。我将编辑我的原始问题以包含我制作的 useApi 自定义钩子。
    【解决方案2】:

    我找到了解决我自己问题的另一种方法!

    我仍然相信我的推理为什么它不起作用。但是,React Router V6 内置了一个更官方的解决方法。我没有在早期版本上测试过。

    您可以使用react-router-dom/react-router 中内置的useSearchParams 挂钩。

    在以下示例中,“?page=”将被定义为搜索参数:

    export default function Component() {
      const [searchParams, setSearchParams] = useSearchParams({});
      const searchObject = Object.fromEntries(searchParams.entries());
      const { page } = searchObject;
      const pageInt = parseInt(page);
    
      return (
        <a onClick={() => {
            e.preventDefault(); // To avoid a complete page load.
            setSearchParams({ ...searchObject, page: `${pageInt + 1}` }
        }}>Update search</a>
      );
    }
    

    以上代码是我设法实现的高度简化版本,因此请随意优化。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-15
      • 1970-01-01
      • 1970-01-01
      • 2016-04-08
      相关资源
      最近更新 更多