React Redux - 混淆使用功能组件与 useDispatch 与 Class 组件和 mapStateToProps

React Redux - Confusion on Using Functional Component with useDispatch vs Class Component and mapStateToProps

我正在尝试让用户能够从所有可能的项目列表中单击一个项目,并打开一个模式来显示有关该项目的数据(包括他们当前拥有的数量)和按钮 increment/decrement那个数额。

据我了解,因为我只是显示正在传入的数据,然后分派一个操作来更新商店,所以我应该使用功能组件来显示数据并使用 Dispatch 来调用商店操作。

目前,当我更新商店时,我在 Redux 调试工具中看到了变化,但在我重新打开它之前,变化不会反映在模态中。虽然我一直在寻找这个问题的答案,但我看到许多类似的问题,但它们都使用 Class 组件和 mapStateToProps(例如 )。我认为最佳实践是除非需要,否则使用功能组件。我是否认为如果我在功能组件中从存储中获取值,它应该在更改时更新?

代码片段

export default function ItemDialog({
    ...
    selectedItem,
}) {
    const dispatch = useDispatch()
    const inventory = useSelector(
        state => state.user.inventory
    )
    let userItem = inventory.find(
        userItem => userItem.name === selectedItem.name
    )

    const changeItemCount = (item, change) => {
        item.change = change
        dispatch({
            type: "USER_INVENTORY_UPDATED",
            payload: item
        })
    }

    const showQuantity = userItem => {
        return userItem.quantity > 0 ? `(${userItem.quantity})` : ""
    }
...

render(
    <p className="text-xl text-center font-semibold">
        {selectedItem.name}
    </p>
    <p className="text-center font-light">
        {showQuantity(userItem)}
    </p>

    ...
    <AddBoxIcon
        onClick={() => changeItemCount(selectedItem, 1)}
    />
)
const userReducer = (state = InitialUserState, action) => {
    let inventoryCopy = { ...state.inventory }

    switch (action.type) {
        case "USER_INVENTORY_UPDATED":
            let category = action.payload.category
            let updatedItemIndex = inventoryCopy[category].findIndex(
                item => item.name === action.payload.name.toUpperCase()
            )

            // If item is already there
            if (updatedItemIndex >= 0) {
                inventoryCopy[category][updatedItemIndex].quantity +=
                    action.payload.change
            } else {
                // If item needs to be added to inventory category
                let newItem = {
                    name: action.payload.name,
                    quantity: action.payload.change
                }
                inventoryCopy[category].push(newItem)
            }

            return {
                ...state,
                inventory: inventoryCopy
            }

            ...

            default:
            return state
    }
}

当您 return 更新状态时,请检查您的传播运算符。您可能需要深度克隆旧状态,具体取决于它有多少嵌套对象。

The docs 有更多关于浅克隆对象的信息。

深度克隆状态对象将帮助您摆脱:

let inventoryCopy = { ...state.inventory }