React Redux中如何通过useSelector实现表单数据按日期排序
Redux架构下实现表单排序的正确方案
排序属于视图交互逻辑,根据作用范围不同有两种实现方式,不要直接修改Redux存储的原始状态。
方案1:组件本地状态管理排序(优先推荐)
如果排序规则只在当前Folder页面使用,完全不需要把排序逻辑放到全局Redux中,原始表单数据全局只存一份即可,排序后的数据作为组件派生状态处理即可。
- 核心注意点:从
useSelector拿到的formData是Redux存储的状态引用,绝对不能直接调用sort修改原数组,必须先浅拷贝再排序 - 实现代码:
import React, { useState, useMemo } from "react"; import { useSelector } from "react-redux"; export const FolderNew = () => { // 获取全局存储的原始表单数据 const formData = useSelector((state) => state.allFormsReducer); // 本地存储当前页面的排序规则,不需要同步到全局 const [sortOrder, setSortOrder] = useState('default'); // 根据原始数据+排序规则,派生渲染用的表单列表,依赖变化时才会重新计算 const displayForms = useMemo(() => { if (sortOrder === 'default') return formData; // 浅拷贝原数组后再排序,避免修改Redux原始状态 return [...formData].sort((a, b) => { return sortOrder === 'desc' ? b.createdAt.localeCompare(a.createdAt) : a.createdAt.localeCompare(b.createdAt) }) }, [formData, sortOrder]) // 点击按钮切换排序规则 const handleDescendSort = () => { setSortOrder('desc'); }; return ( <div> <button onClick={handleDescendSort}>按创建日期降序</button> {/* 列表渲染时统一使用displayForms,不要直接用原始formData */} </div> ) }
方案2:全局管理排序规则(多组件共享时使用)
如果排序后的表单结果需要在多个页面/组件中复用,再把排序逻辑放到Redux中处理,需要新增对应的action和reducer处理逻辑,严格遵守Redux不可变更新原则。
- 新增排序action
在原有actions文件中添加排序对应的action类型和创建函数:
// 新增排序action类型 export const SORT_FORMS = "SORT_FORMS"; // 排序action,接收排序方向作为参数 export const sortForms = (order) => ({ type: SORT_FORMS, payload: order })
- 更新reducer逻辑
调整reducer的存储结构,区分原始数据和排序状态,更新时必须返回新的状态引用,禁止原地修改原数组:
import { GET_ALL_FORMS, SORT_FORMS } from "../actions/forms.actions"; // 调整初始状态结构,分别存储原始列表和排序规则 const initialState = { list: [], sortOrder: 'default' }; export default function allFormsReducer(state = initialState, action) { switch (action.type) { case GET_ALL_FORMS: // 拉取新数据时重置排序规则,更新原始列表 return { ...state, list: action.payload, sortOrder: 'default' }; case SORT_FORMS: { const targetOrder = action.payload; const sortedList = targetOrder === 'default' ? state.list : [...state.list].sort((a, b) => { return targetOrder === 'desc' ? b.createdAt.localeCompare(a.createdAt) : a.createdAt.localeCompare(b.createdAt) }) return { ...state, sortOrder: targetOrder, list: sortedList } } default: return state; } }
- 组件中触发排序action
import React from 'react'; import { useSelector, useDispatch } from "react-redux"; import { sortForms } from '对应action文件路径'; export const FolderNew = () => { const dispatch = useDispatch(); // 注意调整取值路径,匹配新的reducer结构 const formData = useSelector((state) => state.allFormsReducer.list); const descend = () => { dispatch(sortForms('desc')); }; return ( <div> <button onClick={descend}>按创建日期降序</button> {/* 列表渲染逻辑 */} </div> ) }
之前修改reducer不生效的核心原因
Array.sort是原地修改方法,如果直接在reducer中对传入的state数组调用sort,属于直接修改原状态,Redux检测不到状态引用变化,就不会触发组件重新渲染。所有reducer中的状态更新必须返回新的状态对象/数组,不能直接修改入参state。
内容的提问来源于stack exchange,提问作者Elodie Muller
相关产品推荐
相关产品推荐

