如何在 nextjs v13 中设置新的查询参数和退出查询参数(而不是删除)

问题描述 投票:0回答:2
"use client";
import { useCallback, useEffect, useState } from "react";
import Accordion from "../accordion/accordion";
import {
  useRouter,
  usePathname,
  useSearchParams,
  useParams,
} from "next/navigation";
import { getBrandsRequest } from "../../../APIRequest/brand/brandApi";
import capitalizeFLetter from "../../../utils/capitalizedFirstWord/capitalizedFirstWord";

const Brand = () => {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [allBrand, setAllBrand] = useState([]);
  const newSearchParams = new URLSearchParams(searchParams);

  const handleChange = (e, index) => {
    newSearchParams.set("tab", "cami");
  };

  useEffect(() => {
    (async () => {
      let data = await getBrandsRequest();
      setAllBrand(data);
    })();
  }, []);

  let content = (
    <>
      {allBrand?.map((item, index) => (
        <div className="flex items-center gap-x-2" key={index}>
          <label className="dark:text-white sm:text-[14px] flex items-center">
            <input
              className="w-4 sm:w-3 h-4 mr-2 accent-[#ff007f]"
              name={item?.name}
              onChange={(e) => handleChange(e, index + 1)}
              type="checkbox"
              value={item?.name}
            />
            {capitalizeFLetter(item?.name)}
          </label>
        </div>
      ))}
    </>
  );

  return (
    <div className=" max-w-[275px] px-5 border border-gray-200 rounded-lg shadow card w-96 bg-base-100 bg-white dark:bg-gray-700">
      <Accordion title={"Brand"} content={content} />
    </div>
  );
};

export default Brand;

当我单击复选框时运行此代码:

  const handleChange = (e, index) => {
    newSearchParams.set("tab", "cami");
  };

但这显示我为空。

我必须使用如下查询参数的完整网址:http://localhost:3000/store?pageNo=1&perPage=100&searchKeyword=samsung&min=0&max=8000

我想要:http://localhost:3000/store?pageNo=1&perPage=100&searchKeyword=samsung&min=0&max=8000&tab=cami

javascript reactjs next.js
2个回答
0
投票

您可以创建一个钩子来更改参数(甚至替换它们)。 这是一个简单的例子

export const useQueryParams = () => {
  const [queryParams, setQueryParams] = useSearchParams();
  const prevQueryParamsRef = useRef({});

  const filterValues = (values, options) => {
    const newQueryParams = createSearchParams(Object.keys(values).reduce((acc, curr) => {
      if (
        !Array.isArray(values[curr]) && values[curr]
        || Array.isArray(values[curr]) && values[curr].length > 0
      ) {
        acc[curr] = values[curr];
      }
      return acc;
    }, {}));

    setQueryParams(newQueryParams, {
      ...options,
      ...{
        state: options?.state || window.history.state,
      },
    });
  };

  const out = {};

  queryParams.forEach((v, k) => {
    out[k] = v;
  });

  useEffect(() => {
    prevQueryParamsRef.current = out;
  }, [out]);

  return [out, filterValues, prevQueryParamsRef.current];
};

然后你可以使用这样的代码更新单个参数

const [queryParams, setQueryParams] = useQueryParams();

setQueryParams({
  ...queryParams,
  ...{
    page: 3,
  },
});

或者,如果你想替换所有参数

const [queryParams, setQueryParams] = useQueryParams();

setQueryParams({
  ...queryParams,
  ...{
    page: 3,
  },
}, {replace: true}); // <-- add this

0
投票

我创建了一个钩子:

const useQueryNextJS = () => {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();

  const setQuery = ({ key, value }: { key: string; value?: string }) => {
    const current = new URLSearchParams(Array.from(searchParams.entries()));

    if (!value) {
      current.delete(key);
    } else {
      current.set(key, value);
    }

    const search = current.toString();
    const query = search ? `?${search}` : "";
    router.replace(`${pathname}${query}`);
  };

  return {
    setQuery,
  };
};

您可以阅读以下内容:https://github.com/vercel/next.js/discussions/47583

© www.soinside.com 2019 - 2024. All rights reserved.