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

React useEffect执行后filteredProject值正确但页面不更新问题

问题根因

你的判断完全准确,页面不更新的核心原因就是filteredProject不是响应式状态:

  • 你在组件顶层用let filteredProject = projectsList声明的是普通临时变量,每次组件重渲染时,这个变量都会被重置为原始的projectsList值。你在useEffect里对这个普通变量的赋值,既不会触发React的重渲染流程,就算触发了重渲染,修改后的值也会被顶层的重新声明覆盖。
  • 代码逻辑本身也存在不一致:判断筛选值为All的分支里你调用了未声明的setfilteredProject方法,其余分支又直接给普通变量赋值,本身逻辑就没有闭环。
  • 额外的小问题:你给筛选状态state设置的初始值是数字0,但所有单选按钮的value都是字符串类型,首次渲染时过滤逻辑会出现类型不匹配的问题。
修正方案

这类基于现有状态做派生计算的场景,完全不需要使用useEffect,直接在渲染阶段计算过滤结果即可,逻辑更简洁也不会出现状态同步问题,参考代码如下:

// 修正初始值类型,和单选框value保持一致,变量名避免和redux的state重名减少混淆
const [statusFilter, setStatusFilter] = useState("All")
const projectsList = useSelector(state=>state.projectReducer.projects)

// 用useMemo缓存过滤结果,仅在依赖项变化时重新计算,避免不必要的性能消耗
const filteredProject = useMemo(() => {
  if (!projectsList) return []
  if (statusFilter === "All") return projectsList
  return projectsList.filter(item => item.state === statusFilter)
}, [projectsList, statusFilter])

function toggleStatus(e){
  setStatusFilter(e.target.value)
}

return (
  <div className="px-2 py-4 ">
    <div className="card h-fit my-4 lg:w-12/12">
      <div className='form-check form-check-inline'>
        <input 
          className='form-check-input appearance-none h-4 w-4 border border-gray-300 rounded-sm bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer' 
          name='status' 
          type='radio' 
          onChange={toggleStatus} 
          value='All' 
          checked={statusFilter === 'All'}
        />
        <label className='form-check-label inline-block text-gray-800 font-normal mr-2'><b>All Statuses</b></label>
      </div>
      <div className='form-check form-check-inline'>
        <input 
          className='form-check-input appearance-none h-4 w-4 border border-gray-300 rounded-sm bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer' 
          name='status' 
          type='radio' 
          onChange={toggleStatus} 
          value='Fundraising' 
          checked={statusFilter === 'Fundraising'}
        />
        <label className='form-check-label inline-block text-gray-800 font-normal mr-2'>Fundraising</label>
      </div>
      <div className='form-check form-check-inline'>
        <input 
          className='form-check-input appearance-none h-4 w-4 border border-gray-300 rounded-sm bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer' 
          name='status' 
          type='radio' 
          onChange={toggleStatus} 
          value='Successful' 
          checked={statusFilter === 'Successful'}
        />
        <label className='form-check-label inline-block text-gray-800 font-normal mr-2'>Successful</label>
      </div>
      <div className='form-check form-check-inline'>
        <input 
          className='form-check-input appearance-none h-4 w-4 border border-gray-300 rounded-sm bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer' 
          name='status' 
          type='radio' 
          onChange={toggleStatus} 
          value='Expired' 
          checked={statusFilter === 'Expired'}
        />
        <label className='form-check-label inline-block text-gray-800 font-normal mr-2'>Expired</label>
      </div>
    </div>
    <div className="my-2 lg:my-0 lg:mx-2 grid sm:grid-cols-3 sm:gap-2 grid-cols-1">
      {filteredProject.map(/* 原有列表渲染逻辑 */)}
    </div>
  </div>
)

补充说明

  • 单选控件建议用onChange替代onClick,更符合表单交互的规范;同时用checked属性受控绑定状态值,替代defaultChecked的非受控写法,避免选中状态和实际变量值不同步。
  • 如果你坚持要用useEffect实现,必须先把filteredProject声明为响应式状态:const [filteredProject, setFilteredProject] = useState([]),且所有分支都通过setFilteredProject更新值,不能直接给变量赋值。但这种写法会多触发一次组件重渲染,性能不如直接派生计算的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:57:48