React:如何使用下拉菜单动态排序对象数组(使用 React Hooks)

2025-06-10

React:如何使用下拉菜单动态排序对象数组(使用 React Hooks)

假设我们有以下问题:

  • 对对象数组进行排序
  • 根据不同的属性值动态地执行
  • 使用react.js在浏览器中呈现

好的,让我们开始谈正事吧!

对象示例数组:



const bands = [
  {
    name: 'Nightwish',
    albums: 9,
    members: 6,
    formed_in: 1996,
  },
  {
    name: 'Metallica',
    albums: 10,
    members: 4,
    formed_in: 1981,
  },
  {
    name: 'Nirvana',
    albums: 3,
    members: 3,
    formed_in: 1987,
  },
];


Enter fullscreen mode Exit fullscreen mode

为了本教程的目的,我不会做任何花哨的组件,所以让我们在普通的div中呈现这个数组。



function App() {
  return (
    <div className="App">
      {bands.map(band => (
        <div key={band.id} style={{ margin: '30px' }}>
          <div>{`Band: ${band.name}`}</div>
          <div>{`Albums: ${band.albums}`}</div>
          <div>{`Members: ${band.members}`}</div>
          <div>{`Year of founding: ${band.formed_in}`}</div>
        </div>
      ))}
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

检查浏览器中的视图:

乐队

看起来不错!

现在让我们添加具有可排序属性选项的选择元素。



<select>
        <option value="albums">Albums</option>
        <option value="members">Members</option>
        <option value="formed">Formed in</option>
</select>


Enter fullscreen mode Exit fullscreen mode

这太棒了,但是当我们改变下拉选项时什么也没有发生。

下拉菜单

为了解决这个问题,我们需要以某种方式连接选择元素和我们想要排序的数组,并在每次选择不同的选择选项时重新呈现排序后的数组值。

根据React 的文档

默认情况下,当你的组件的状态或道具发生变化时,你的组件将重新渲染。

这意味着我们必须向组件添加状态。我将借助React Hooks来完成此操作。

让我们使用useState hook定义状态变量数据及其更新方法setData



const [data, setData] = useState([]);


Enter fullscreen mode Exit fullscreen mode

假设,当状态将使用新数据(已排序的数组)更新时,组件应该重新渲染。为了测试它,我们需要定义一个函数,该函数将根据下拉菜单中的选定选项对 bands 数组进行排序,并在每次选定选项发生变化时调用它。



...
const sortArray = type => {
    const types = {
      albums: 'albums',
      members: 'members',
      formed: 'formed_in',
    };
    const sortProperty = types[type];
    const sorted = bands.sort((a, b) => b[sortProperty] - a[sortProperty]);
    console.log(sorted);
    setData(sorted);
  };

...
<select onChange={(e) => sortArray(e.target.value)}>
...


Enter fullscreen mode Exit fullscreen mode

但是当我们运行代码时,它不能正常工作。

成员排序

专辑排序

数组排序正常,控制台里打印了结果,但数组数据并没有重新渲染。只有当我们第一次更改排序后的值时,它才会重新渲染。

问题如下,正如React 文档中所述:

不要直接修改状态

所以,这行代码是错误的,因为它就修改了 state(对当前 state 中的数组进行排序) 。而 React “认为” setData调用的是它已经拥有的同一个数组,因此不会重新渲染。(非常感谢TJ Crowder帮我澄清了这个问题)



const sorted = bands.sort((a, b) => b[sortProperty] - a[sortProperty]);


Enter fullscreen mode Exit fullscreen mode

正确的方法是先复制 bands 数组,对其进行排序,然后使用该数组调用setData 方法。因此,只需在复制数组时添加扩展运算符即可解决问题。



const sorted = [...bands].sort((a, b) => b[sortProperty] - a[sortProperty]);


Enter fullscreen mode Exit fullscreen mode

我们试着运行一下代码。嗯,代码能运行,但是一开始,也就是在 select 选项改变之后,bands 数据并没有渲染出来。

借助useEffect Hook 可以轻松解决这个问题。

1.定义另一个状态变量来存储 sort 属性的值。默认情况下,bands 数组将按专辑数量排序。



const [sortType, setSortType] = useState('albums');


Enter fullscreen mode Exit fullscreen mode

2.在选择选项改变时更新sortType的值。



<select onChange={(e) => setSortType(e.target.value)}>


Enter fullscreen mode Exit fullscreen mode

3. 添加useEffect Hook,它将在组件渲染后调用sortArray函数,并在每次更新sortType值时调用。我们通过将第二个参数 ( sortType ) 传递给useEffect来实现这一点,该参数是 effect 所依赖的值数组。



useEffect(() => {
    const sortArray = type => {
      const types = {
        albums: 'albums',
        members: 'members',
        formed: 'formed_in',
      };
      const sortProperty = types[type];
      const sorted = [...bands].sort((a, b) => b[sortProperty] - a[sortProperty]);
      setData(sorted);
    };

    sortArray(sortType);
  }, [sortType]);


Enter fullscreen mode Exit fullscreen mode

现在代码可以按预期工作了!

完整的源代码可以在这个 GitHub 仓库中找到

最初发布在我自己的博客上

链接:https://dev.to/ramonak/react-how-to-dynamically-sort-an-array-of-objects-using-the-dropdown-with-react-hooks-195p
PREV
Nodejs 多租户架构构建指南
NEXT
初级前端开发人员的项目构想👨‍💻🦄