如何将我的params复选框从react-router-dom移动到next js 13

bweufnob  于 12个月前  发布在  React
关注(0)|答案(1)|浏览(92)

我有一个React应用程序,它使用react-router-dom来管理URL参数和用于过滤项目的复选框。下面是我的代码的简化版本:

import React, { useState, useEffect } from "react";
import { useSearchParams, useNavigate } from "react-router-dom";

const sexData = [
  { value: "male", name: "Male" },
  { value: "female", name: "Female" },
];

const colorData = [
  { value: "red", name: "Red" },
  { value: "blue", name: "Blue" },
  { value: "green", name: "Green" },
];

const categoryData = [
  { value: "clothing", name: "Clothing" },
  { value: "shoes", name: "Shoes" },
  { value: "accessories", name: "Accessories" },
];

const sizeData = [
  { value: "small", name: "Small" },
  { value: "medium", name: "Medium" },
  { value: "large", name: "Large" },
];

export default function App() {
  const navigation = useNavigate();
  const [selectedItems, setSelectedItems] = useState(() => {
    const initialItems = {
      sex: {},
      colors: {},
      categories: {},
      size: {},
    };
    return initialItems;
  });

  const [searchParams] = useSearchParams();

  useEffect(() => {
    const currentParams = Object.fromEntries([...searchParams]);
    updateSelectedItems(currentParams);
  }, [searchParams]);

  const updateSelectedItems = (params) => {
    const newItems = { ...selectedItems };
    for (const key in newItems) {
      if (params[key]) {
        const itemList = params[key].split(",");
        newItems[key] = itemList.reduce((acc, item) => {
          acc[item] = true;
          return acc;
        }, {});
      }
    }
    setSelectedItems(newItems);
  };

  const handleOnChange = (group, value) => {
    const updatedItems = { ...selectedItems };
    if (!updatedItems[group][value]) {
      updatedItems[group][value] = true;
    } else {
      delete updatedItems[group][value];
    }
    setSelectedItems(updatedItems);

    // Update URL params
    const paramArray = [];
    for (const key in updatedItems) {
      const selectedItemsArray = Object.keys(updatedItems[key]);
      if (selectedItemsArray.length > 0) {
        const paramString = selectedItemsArray.join(",");
        paramArray.push(`${key}=${paramString}`);
      }
    }
    const queryParams = paramArray.join("&");
    navigation(`/?${queryParams}`);
  };

  const renderList = (group, title, data) => (
    <div className="item-group">
      <h3>Select {title}</h3>
      <ul className="item-list">
        {data.map(({ value, name }, index) => (
          <li key={index}>
            <div className="item-list-item">
              <div className="left-section">
                <input
                  type="checkbox"
                  id={`custom-checkbox-${group}-${index}`}
                  name={name}
                  value={value}
                  checked={selectedItems[group][value] || false}
                  onChange={() => handleOnChange(group, value)}
                />
                <label htmlFor={`custom-checkbox-${group}-${index}`}>{name}</label>
              </div>
            </div>
          </li>
        ))}
      </ul>
    </div>
  );

  return (
    <div className="App">
      {renderList("sex", "Sex", sexData)}
      {renderList("colors", "Colors", colorData)}
      {renderList("categories", "Categories", categoryData)}
      {renderList("size", "Size", sizeData)}
    </div>
  );
}

在这段代码中,我有复选框,允许用户根据各种标准(例如,性别,颜色,类别,大小)过滤项目。这些复选框会更新URL参数以反映用户的选择,从而可以共享筛选的视图或将其添加为书签。
我正在尝试用Next.js 13来实现这一点,所以我希望用Next.js中的路由来替换react-router-dom。但是,我不确定如何处理URL参数,以及在Next.js应用程序中选中复选框时更新URL。
我没有遇到任何具体的错误。我的问题是理解如何使用Next.js实现相同的URL参数管理和复选框行为。
我试着使用这个链接来查看Next.js文档:https://nextjs.org/docs/app/api-reference/functions/use-search-params虽然,我不知道如何在我的代码中翻译它们。

vulvrdjw

vulvrdjw1#

您可以利用Next.js的内置路由功能并相应修改代码

在下面的代码中:

  • useSearchParams钩子被Next.js中的useRouter钩子替换,后者提供对路由器对象的访问。*
  • useNavigate函数替换为路由器对象的push method以更新URL。*
  • searchParams对象替换为router.query,其中包含来自URL的查询参数。*
  • navigation variable替换为router object。*
import { useRouter } from "next/router";
import { useEffect, useState } from "react";

const sexData = [
  { value: "male", name: "Male" },
  { value: "female", name: "Female" },
];

const colorData = [
  { value: "red", name: "Red" },
  { value: "blue", name: "Blue" },
  { value: "green", name: "Green" },
];

const categoryData = [
  { value: "clothing", name: "Clothing" },
  { value: "shoes", name: "Shoes" },
  { value: "accessories", name: "Accessories" },
];

const sizeData = [
  { value: "small", name: "Small" },
  { value: "medium", name: "Medium" },
  { value: "large", name: "Large" },
];

export default function App() {
  const router = useRouter();
  const [selectedItems, setSelectedItems] = useState(() => {
    const initialItems = {
      sex: {},
      colors: {},
      categories: {},
      size: {},
    };
    return initialItems;
  });

  useEffect(() => {
    const currentParams = router.query;
    updateSelectedItems(currentParams);
  }, [router.query]);

  const updateSelectedItems = (params) => {
    const newItems = { ...selectedItems };
    for (const key in newItems) {
      if (params[key]) {
        const itemList = params[key].split(",");
        newItems[key] = itemList.reduce((acc, item) => {
          acc[item] = true;
          return acc;
        }, {});
      }
    }
    setSelectedItems(newItems);
  };

  const handleOnChange = (group, value) => {
    const updatedItems = { ...selectedItems };
    if (!updatedItems[group][value]) {
      updatedItems[group][value] = true;
    } else {
      delete updatedItems[group][value];
    }
    setSelectedItems(updatedItems);

    // Update URL params
    const queryParams = Object.entries(updatedItems)
      .filter(([key, value]) => Object.keys(value).length > 0)
      .map(([key, value]) => `${key}=${Object.keys(value).join(",")}`)
      .join("&");

    router.push(`/?${queryParams}`);
  };

  const renderList = (group, title, data) => (
    <div className="item-group">
      <h3>Select {title}</h3>
      <ul className="item-list">
        {data.map(({ value, name }, index) => (
          <li key={index}>
            <div className="item-list-item">
              <div className="left-section">
                <input
                  type="checkbox"
                  id={`custom-checkbox-${group}-${index}`}
                  name={name}
                  value={value}
                  checked={selectedItems[group][value] || false}
                  onChange={() => handleOnChange(group, value)}
                />
                <label htmlFor={`custom-checkbox-${group}-${index}`}>{name}</label>
              </div>
            </div>
          </li>
        ))}
      </ul>
    </div>
  );

  return (
    <div className="App">
      {renderList("sex", "Sex", sexData)}
      {renderList("colors", "Colors", colorData)}
      {renderList("categories", "Categories", categoryData)}
      {renderList("size", "Size", sizeData)}
    </div>
  );
}

相关问题