【问题标题】:React Redux - Confusion on Using Functional Component with useDispatch vs Class Component and mapStateToPropsReact Redux - 使用功能组件与 useDispatch 与类组件和 mapStateToProps 的混淆
【发布时间】:2020-05-23 20:45:54
【问题描述】:

我试图让用户能够从所有可能项目的列表中单击一个项目,并打开一个模式以显示有关该项目的数据(包括他们拥有的当前数量)和用于增加/减少该数量的按钮.

据我了解,因为我只是显示正在传入的数据,然后调度一个动作来更新存储,我应该使用功能组件来显示数据并使用 Dispatch 来调用存储动作。

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

代码片段

  • 对话框
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
    }
}

【问题讨论】:

  • 你可以拥有一个无状态的功能组件,并从容器中传递一个动作创建者;它不需要是一个类。
  • 所以您的计数没有更新或没有显示整个数据?
  • 你能发布你的商店状态吗?我给出的答案很模糊,因为我不知道状态对象是什么样的。

标签: javascript reactjs redux store


【解决方案1】:

在您返回更新后的状态时检查您的扩展运算符。您可能需要深度克隆旧状态,具体取决于它有多少嵌套对象。

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

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

let inventoryCopy = { ...state.inventory }

【讨论】:

  • Store 有一个 User reducer,它是一个具有不同类别的对象作为键(如衣服),每个类别中可能有子类别。可能克隆是问题所在是有道理的。
  • 我刚刚更新了我的操作,在商店的每个级别创建了一个副本,然后更新了相关级别,将其反馈到商店的更高级别,并修复了它。非常感谢!
  • 是的,你正在改变你的状态。我鼓励您开始使用我们的新 Redux Toolkit package,它会在检测到突变时引发错误,并且还允许您编写更简单的 reducer 逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 2021-03-19
  • 2017-05-17
  • 2019-03-22
  • 2020-06-18
  • 2021-10-23
  • 2021-08-11
相关资源
最近更新 更多