在React/Next.js数据过滤中保留先前的过滤器并添加新的过滤器。

huangapple go评论68阅读模式
英文:

Preserving Previous Filters and Adding New Filters in React/Next.js Data Filtering

问题

我目前正在尝试使用React/Next.js来过滤数据,但我遇到了一个问题。当我设置一个新的过滤器时,之前的过滤器被删除了。例如,如果用户执行搜索,它可以正常工作,但标签过滤器从URL中删除了。

我想要的是保留先前的过滤器,并在已经设置的情况下添加或更新新的过滤器。例如,URL可以是:localhost:3000/?search=text&tag=food。

我的搜索输入代码:

import React, { useState } from "react";
import { XMarkIcon } from "@heroicons/react/24/outline";

export default function Search({ useRouter, search }) {
  const [searchQuery, setSearchQuery] = useState(search);
  const { push } = useRouter();

  const handleInputChange = (e) => {
    setSearchQuery(e.target.value);
    push("/?search=" + e.target.value);
  };

  const cleanSearch = (e) => {
    e.preventDefault();
    setSearchQuery("");
    push("/?search=");
  };

  return (
    // 其他部分...
    <input
      type="search"
      id="default-search"
      className="block w-full rounded-lg border border-slate-300 bg-slate-50 p-4 pl-10 text-sm  placeholder-slate-400 focus:border-blue-500 focus:ring-blue-500"
      placeholder="Search AI tool or category"
      required
      value={searchQuery}
      onChange={handleInputChange}
    />
    // 其他部分...
  );
}

我的过滤器组件:

"use client";
import React from "react";
import Search from "../common/search";
import Selector from "../common/selector";
import { useRouter } from "next/navigation";

export default function Filters({ tags, prices, search }) {
  return (
    <div className="mb-5 flex w-full grid-cols-4 flex-col gap-3 text-center text-base font-medium text-slate-700 md:grid">
      <Search
        className="col-span-2 w-full"
        search={search}
        useRouter={useRouter}
      />
      <Selector label="Category" data={tags} useRouter={useRouter} />
      <Selector label="Price" data={prices} useRouter={useRouter} />
    </div>
  );
}

在搜索组件中,我尝试添加的而不是直接推送的内容是:

const handleInputChange = (e) => {
  setSearchQuery(e.target.value);
  updateQueryParams({ search: e.target.value });
};

const updateQueryParams = (newParams) => {
  const existingQueryParams = { ...router.query };
  const updatedQueryParams = { ...existingQueryParams, ...newParams };

  let queryString = router.pathname; // 初始化为 router.pathname

  const queryKeys = Object.keys(updatedQueryParams);
  if (queryKeys.length > 0) {
    const queryArray = queryKeys.map((key) => `${key}=${updatedQueryParams[key]}`);
    queryString += `?${queryArray.join("&")}`;
  }

  router.push(queryString);
};
英文:

I'm currently trying to filter data using React/Next.js, but I'm facing an issue. When I set a new filter, the previous ones are being removed. For example, if the user performs a search, it works fine, but the tag filters are removed from the URL.

What I would like is to preserve the previous filters and add or update a new filter if it's already set up. For example, the URL could be: localhost:3000/?search=text&tag=food.

My search input code:

import React, { useState } from &quot;react&quot;;
import { XMarkIcon } from &quot;@heroicons/react/24/outline&quot;;

export default function Search({ useRouter, search }) {
  const [searchQuery, setSearchQuery] = useState(search);
  const { push } = useRouter();

  const handleInputChange = (e) =&gt; {
    setSearchQuery(e.target.value);
    push(&quot;/?search=&quot; + e.target.value);
  };

  const cleanSearch = (e) =&gt; {
    e.preventDefault();
    setSearchQuery(&quot;&quot;);
    push(&quot;/?search=&quot;);
  };

return (..................
          &lt;input
            type=&quot;search&quot;
            id=&quot;default-search&quot;
            className=&quot;block w-full rounded-lg border border-slate-300 bg-slate-50 p-4 pl-10 text-sm  placeholder-slate-400 focus:border-blue-500 focus:ring-blue-500&quot;
            placeholder=&quot;Search AI tool or category&quot;
            required
            value={searchQuery}
            onChange={handleInputChange}
          /&gt;
    ................);}

My filter component :

&quot;use client&quot;;
import React from &quot;react&quot;;
import Search from &quot;../common/search&quot;;
import Selector from &quot;../common/selector&quot;;
import { useRouter } from &quot;next/navigation&quot;;

export default function Filters({ tags, prices, search }) {
  return (
    &lt;div className=&quot;mb-5 flex w-full grid-cols-4 flex-col gap-3 text-center text-base font-medium text-slate-700 md:grid&quot;&gt;
      &lt;Search
        className=&quot;col-span-2 w-full&quot;
        search={search}
        useRouter={useRouter}
      /&gt;
      &lt;Selector label=&quot;Category&quot; data={tags} useRouter={useRouter} /&gt;
      &lt;Selector label=&quot;Price&quot; data={prices} useRouter={useRouter} /&gt;
    &lt;/div&gt;
  );
}

What I tried to add in the search component instead of pushing directly was:

  const handleInputChange = (e) =&gt; {
    setSearchQuery(e.target.value);
    updateQueryParams({ search: e.target.value });
  };

const updateQueryParams = (newParams) =&gt; {
  const existingQueryParams = { ...router.query };
  const updatedQueryParams = { ...existingQueryParams, ...newParams };

  let queryString = router.pathname; // Initialize with router.pathname

  const queryKeys = Object.keys(updatedQueryParams);
  if (queryKeys.length &gt; 0) {
    const queryArray = queryKeys.map((key) =&gt; `${key}=${updatedQueryParams[key]}`);
    queryString += `?${queryArray.join(&quot;&amp;&quot;)}`;
  }

  router.push(queryString);
};```


</details>


# 答案1
**得分**: 0

Your problem is you're just using the last e.target.value for the new search parameter.

Instead of

```javascript
const handleInputChange = (e) => {
  setSearchQuery(e.target.value);
  push("/?search=" + e.target.value);
};

Try making your searchQuery an array and go with something more like this:

const handleInputChange = (e) => {
  setSearchQuery((oldSearch) => [...oldSearch, e.target.value]);
  push("/?search=" + searchQuery.join('&'));
};
英文:

Your problem is you're just using the last e.target.value for the new search parameter.

Instead of

const handleInputChange = (e) =&gt; {
setSearchQuery(e.target.value);
push(&quot;/?search=&quot; + e.target.value);
};

Try making your searchQuery an array and go with something more like this:

const handleInputChange = (e) =&gt; {
setSearchQuery((oldSearch) =&gt; {[...oldSearch, e.target.value]);
push(&quot;/?search=&quot; + searchQuery.join(&#39;&amp;&#39;);
};

huangapple
  • 本文由 发表于 2023年6月2日 05:11:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76385736.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定