React Redux - путаница при использовании функционального компонента с useDispatch vs Class Component и mapStateToProps - PullRequest
1 голос
/ 07 февраля 2020

Я пытаюсь, чтобы пользователь мог щелкнуть элемент из списка всех возможных элементов и открыть модальное окно для отображения данных об этом элементе (включая текущее количество, которое он имеет) и кнопок для увеличения / уменьшения этого количества. .

Насколько я понимаю, поскольку я просто показываю данные, которые передаются, а затем отправляю действие для обновления хранилища, я должен использовать функциональный компонент для отображения данных и использовать Dispatch для вызова действия хранилища.

В настоящее время, когда я обновляю магазин, я вижу изменения в инструментах отладки Redux, но это изменение не отражается в модальном режиме, пока я не открою его снова. Пока я искал ответы на эти вопросы, я вижу много похожих вопросов, но все они используют компоненты класса и 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
    }
}

1 Ответ

1 голос
/ 07 февраля 2020

Проверьте свой оператор спреда, когда вы вернете обновленное состояние. Вам может потребоваться глубокое клонирование старого состояния в зависимости от того, сколько у него вложенных объектов.

Документы содержат больше информации о мелких объектах клонирования.

Глубокое клонирование вашего состояния объект поможет вам избавиться от:

let inventoryCopy = { ...state.inventory }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...