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

Redux dispatch action后如何给React返回响应并单独更新对应点击按钮状态

解决方案

出现该问题的核心原因是Redux中存储的是全局统一的按钮状态,没有和每行的唯一标识绑定,状态更新时所有按钮都会响应变更。可按以下步骤修改:

  1. 调整Redux存储的状态结构,用数组存储正在操作/操作完成的商品唯一ID,代替原来的单一布尔值状态
    示例Reducer代码:
// orderReducer.js
const initialState = {
  // 存储正在提交购买请求的商品ID
  buyingItemIds: [],
  // 存储购买成功的商品ID
  boughtItemIds: []
}

export default function orderReducer(state = initialState, action) {
  switch(action.type) {
    case 'START_BUY':
      return {
        ...state,
        buyingItemIds: [...state.buyingItemIds, action.payload.itemId]
      }
    case 'BUY_SUCCESS':
      return {
        ...state,
        buyingItemIds: state.buyingItemIds.filter(id => id !== action.payload.itemId),
        boughtItemIds: [...state.boughtItemIds, action.payload.itemId]
      }
    case 'BUY_FAIL':
      return {
        ...state,
        buyingItemIds: state.buyingItemIds.filter(id => id !== action.payload.itemId)
      }
    default:
      return state
  }
}
  1. 修改action逻辑,请求发起、成功、失败三个阶段分别触发对应action,传入当前操作的商品ID
    修改后的action.js代码:
// 注意异步action需要搭配redux-thunk中间件使用
export const additemtobuy = (data) => async (dispatch) => { 
  const currentItemId = data.id
  // 请求发起前标记当前商品为购买中
  dispatch({ type: 'START_BUY', payload: { itemId: currentItemId } })
  try {
    await axios.post('/api/order', data)
    console.log('items bought')
    // 请求成功标记当前商品为已购买
    dispatch({ type: 'BUY_SUCCESS', payload: { itemId: currentItemId } })
  } catch (err) {
    console.error('购买失败', err)
    // 请求失败清除当前商品的购买中标记
    dispatch({ type: 'BUY_FAIL', payload: { itemId: currentItemId } })
  }
}
  1. 表格组件中每个按钮根据当前行ID匹配Redux中的状态数组,单独控制自身的样式、文案和禁用状态
    修改后的表格组件代码:
import { useSelector, useDispatch } from 'react-redux'
import { additemtobuy } from './action'

const Table = () => { 
  const dispatch = useDispatch()
  // 从Redux取状态
  const { buyingItemIds, boughtItemIds } = useSelector(state => state.order)
  // 假设你的表格行是遍历tableData渲染,每个item自带唯一id字段
  const tableData = [/* 你的表格数据源 */]

  const handleBuy = (data) => {
    dispatch(additemtobuy(data))
  }

  return (
    <table>
      {tableData.map(item => (
        <tr key={item.id}>
          <td>其他列内容</td>
          <td>
            <button
              className={`btn ${
                boughtItemIds.includes(item.id) ? 'btn-secondary' 
                : buyingItemIds.includes(item.id) ? 'btn-warning' 
                : 'btn-primary btn-success'
              }`}
              type="button" 
              onClick={() => handleBuy(item)}
              disabled={buyingItemIds.includes(item.id) || boughtItemIds.includes(item.id)}
            >
              {boughtItemIds.includes(item.id) ? '已购买' 
               : buyingItemIds.includes(item.id) ? '提交中...'
               : <i className="fa fa-check" />
              }
            </button>
          </td>
        </tr>
      ))}
    </table>
  )
}

export default Table

如果不需要全局共享按钮状态,也可以直接在表格组件内部用state存储操作中的ID数组,不需要走Redux,逻辑完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 09:12:03