You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Hook结合Redux Toolkit排序卡片失效问题求助

问题:卡片首次渲染不排序,仅强制刷新后生效

我正在编写自定义Hook实现卡片排序,卡片首次渲染时显示API返回的默认顺序,只有按下Ctrl+S保存触发Vite更新(强制重新渲染)后才会完成排序。刚接触自定义Hook,不清楚问题所在,怀疑是useEffect内的dispatch操作有问题,请问如何让卡片正常排序?

自定义Hook代码

import { useEffect, useState } from 'react';
// Redux
import { getAllBosses, SortBosses } from '../redux/slices/Bosses';
import { useDispatch, useSelector } from 'react-redux';

export default function useFetch(value) {
    const dispatch = useDispatch();
    const { list: bosses } = useSelector(state => state.bosses);
    const [type, setType] = useState([]);

    useEffect(() => {
        value === 'default'
            ? dispatch(getAllBosses())
            : dispatch(SortBosses(value));
        setType(bosses);
    }, [value]);

    return type;
}

组件代码

import { useEffect, useState } from 'react';
// Redux
// import { getAllBosses } from '../../redux/slices/Bosses';
// import {  useDispatch, useSelector } from 'react-redux';

// components
import { BossCard, Loading, Pagination, Error } from '@components';

import { useFetch } from '../../hooks';

import { Cards } from '@components/styles/Cards.style';

function BossesList() {
    // const dispatch = useDispatch();
    const bosses = useFetch('ztoa');
    const [currentPage, setCurrentPage] = useState(1);
    const bossPerPage = 8;
    const indexOfLastBoss = currentPage * bossPerPage;
    const indexOfFirstBoss = indexOfLastBoss - bossPerPage;
    const currentBosses = bosses.slice(indexOfFirstBoss, indexOfLastBoss);

    const pages = pageNumber => {
        setCurrentPage(pageNumber);
    };

    // useEffect(() => {
    //  dispatch(getAllBosses());
    // }, [dispatch]);

    useEffect(() => {
        setCurrentPage(1);
    }, [bosses]);

    return (
        <>
            <Cards>
                {currentBosses.length !== 0 ? (
                    currentBosses.map((boss, index) =>
                        boss.error ? (
                            <Error key={index} error={'No boss with that name.'} />
                        ) : (
                            <BossCard
                                key={boss.id}
                                id={boss.id}
                                name={boss.name}
                                image={boss.image}
                            />
                        )
                    )
                ) : (
                    <div>
                        <Loading />
                    </div>
                )}
            </Cards>
            <Pagination
                bossPerPage={bossPerPage}
                bosses={bosses.length}
                currentBosses={currentBosses}
                pages={pages}
                currentPage={currentPage}
            />
        </>
    );
}

export default BossesList;

问题原因

核心问题是Redux的状态更新是异步的:你在useEffect里调用dispatch(SortBosses(value))后,立刻执行setType(bosses),这时候Redux还没完成状态更新,bosses还是初始的默认数据,所以type拿到的不是排序后的结果。只有当组件强制重新渲染时,useSelector才会读取到Redux里更新后的排序数据,type才会同步。

另外,你在Hook里维护的type state完全是多余的——useSelector会自动监听Redux状态变化,一旦状态更新就会触发组件重新渲染,直接返回bosses就行。

修复方案

1. 修改自定义Hook

去掉多余的type state,直接返回useSelector获取的bosses,同时完善useEffect的依赖项:

import { useEffect } from 'react';
// Redux
import { getAllBosses, SortBosses } from '../redux/slices/Bosses';
import { useDispatch, useSelector } from 'react-redux';

export default function useFetch(value) {
    const dispatch = useDispatch();
    const { list: bosses } = useSelector(state => state.bosses);

    useEffect(() => {
        // 触发对应的数据获取/排序操作
        if (value === 'default') {
            dispatch(getAllBosses());
        } else {
            dispatch(SortBosses(value));
        }
    }, [dispatch, value]); // 加上dispatch和value作为依赖

    return bosses;
}

2. 调整组件逻辑

因为现在bosses直接来自Redux,状态更新会自动触发重新渲染,原来的分页重置逻辑可以保留,但注意如果bosses是数组,依赖项会在数组引用变化时触发,这符合需求:

// ... 其他代码不变

useEffect(() => {
    setCurrentPage(1);
}, [bosses]);

// ... 其他代码不变

这样修改后,当组件首次渲染时,useEffect会触发SortBosses('ztoa'),Redux状态更新后,useSelector会立刻拿到排序后的bosses,组件会重新渲染并显示排序后的卡片,无需等待强制刷新。

内容的提问来源于stack exchange,提问作者Dumbasswithaname

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 08:05:33