如何实现点击按钮对JSON数组按年份、名称排序并切换升降序
实现方案
你之前的写法有三个核心问题:
- 按钮的value是硬编码的固定空值,每次点击触发事件拿到的value永远是空,逻辑判断永远只会走到第一个分支,自然不会切换状态
Array.sort()是原地排序方法,直接修改原数组会引发不可预期的渲染问题,排序前建议先对原数组做浅拷贝- 之前的标题排序直接返回布尔值,不符合sort回调需要返回数字的规范,多语言场景下建议用
localeCompare处理字符串排序更稳妥
你可以按如下逻辑改造代码:
第一步:调整state结构
用一个对象同时存储当前排序字段和排序方向,方便切换逻辑处理:
import { useState } from 'react'; // 组件内定义state const [sortConfig, setSortConfig] = useState({ field: null, // 可选值:'year' 按年份排序 / 'title' 按名称排序 direction: 'asc' // 可选值:'asc' 升序 / 'desc' 降序 });
第二步:编写按钮点击处理逻辑
两个按钮分别对应年份和名称排序,点击同一个按钮时自动切换排序方向:
// 年份排序按钮点击处理 const handleYearSort = () => { setSortConfig(prev => { // 如果当前已经是按年份排序,就翻转排序方向 if (prev.field === 'year') { return { ...prev, direction: prev.direction === 'asc' ? 'desc' : 'asc' } } // 如果之前不是按年份排序,默认按升序(从旧到新)开始排序 return { field: 'year', direction: 'asc' } }) } // 名称排序按钮点击处理 const handleTitleSort = () => { setSortConfig(prev => { if (prev.field === 'title') { return { ...prev, direction: prev.direction === 'asc' ? 'desc' : 'asc' } } return { field: 'title', direction: 'asc' } }) }
第三步:调整排序渲染逻辑
排序前先浅拷贝原数组,避免修改原数据,同时优化排序回调逻辑:
const showResults = [...movies] // 浅拷贝原数组,避免原地修改 .sort((a, b) => { const { field, direction } = sortConfig; // 没有选择排序字段时返回0,保持原顺序 if (!field) return 0; let compareResult = 0; if (field === 'year') { compareResult = a.Year - b.Year; } else if (field === 'title') { // 用localeCompare处理字符串排序,支持中英文混合场景 compareResult = a.Title.localeCompare(b.Title); } // 如果是降序,就把比较结果取反 return direction === 'asc' ? compareResult : -compareResult; }) .map((movie, idx) => ( <div key={idx}> <div> <h4>{movie.Year}</h4> <h3>{movie.Title}</h3> </div> </div> ));
第四步:渲染切换按钮
还可以动态修改按钮文案,直观显示当前排序状态:
{/* 年份排序按钮 */} <button onClick={handleYearSort}> 按年份排序 {sortConfig.field === 'year' && ( <span>{sortConfig.direction === 'asc' ? ' 从旧到新' : ' 从新到旧'}</span> )} </button> {/* 名称排序按钮 */} <button onClick={handleTitleSort}> 按名称排序 {sortConfig.field === 'title' && ( <span>{sortConfig.direction === 'asc' ? ' A-Z' : ' Z-A'}</span> )} </button>
如果不需要同时显示当前排序状态,直接去掉按钮内的条件渲染部分即可,点击切换逻辑不受影响。
内容的提问来源于stack exchange,提问作者Arttu
相关产品推荐
相关产品推荐

