Redux dispatch action后如何给React返回响应并单独更新对应点击按钮状态
解决方案
出现该问题的核心原因是Redux中存储的是全局统一的按钮状态,没有和每行的唯一标识绑定,状态更新时所有按钮都会响应变更。可按以下步骤修改:
- 调整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 } }
- 修改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 } }) } }
- 表格组件中每个按钮根据当前行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
相关产品推荐
相关产品推荐

