首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Redux中将对象添加到嵌套数组中

在Redux中将对象添加到嵌套数组中
EN

Stack Overflow用户
提问于 2020-07-02 07:30:49
回答 1查看 140关注 0票数 1

我正在尝试在banking_cards array数组中添加一个新卡。banking_cards数组位于paymentMethods数组中。因此,我想在banking_cards数组中插入新的card对象。下面的代码会产生一个错误,上面写着state.paymentMethods.banking_cards is not iterable

注意到

banking_cards数组位于paymentMethods数组中。

代码语言:javascript
复制
export const initialState = {
    paymentMethods: [],
  };



  case paymentMethodConstants.ADD_CARD_SUCCESS:
    return {
      ...state,
      paymentMethods: [
        ...state.paymentMethods,
        banking_cards: [...state.paymentMethods.banking_cards, action.payload],
      ],
    };

JSON

代码语言:javascript
复制
paymentMethods = [
  {
    "id": 8,
    "customer_token": "epofjoe",
    "banking_cards": [
      {
        "id": 1,
        "banking_token": "AAA",
        "last_4": "0006",
        "exp_year": 2021,
        "exp_month": 12,
        "cvc": 876
      },
      {
        "id": 2,
        "banking_token": "BBB",
        "last_4": "0002",
        "exp_year": 2022,
        "exp_month": 12,
        "cvc": 877
      },
    ]
  }
]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-02 10:20:17

当将卡添加到支付方法时,您的操作需要包含需要添加到的支付方法。

下面是一个如何做到这一点的工作示例:

代码语言:javascript
复制
const { Provider, useDispatch, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;

const createId = ((id) => () => id++)(3);

const initialState = {
  paymentMethods: [
    {
      id: 8,
      banking_cards: [
        {
          id: 1,
        },
        {
          id: 2,
        },
      ],
    },
    {
      id: 9,
      banking_cards: [
        {
          id: 1,
        },
        {
          id: 2,
        },
      ],
    },
  ],
};
//action types
const ADD_CARD_SUCCESS = 'ADD_CARD_SUCCESS';
//action creators
const addCardSuccess = (payementMethodId, card) => ({
  type: ADD_CARD_SUCCESS,
  payload: { payementMethodId, card },
});
const reducer = (state, { type, payload }) => {
  if (type === ADD_CARD_SUCCESS) {
    const { payementMethodId, card } = payload;
    return {
      ...state,
      paymentMethods: state.paymentMethods.map((method) =>
        method.id === payementMethodId
          ? {
              ...method,
              banking_cards: [
                ...method.banking_cards,
                card,
              ],
            }
          : method
      ),
    };
  }
  return state;
};
//selectors
const selectPaymentMethods = (state) =>
  state.paymentMethods;
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(() => (next) => (action) =>
      next(action)
    )
  )
);
//pure component so not re rendering when nothing changed
const Card = React.memo(function Card({ card }) {
  return <li>card: {card.id}</li>;
});
//pure component so it won't re render when nothing changes
const PaymentMethod = React.memo(function PaymentMethod({
  paymentMethod,
}) {
  const dispatch = useDispatch();
  return (
    <li>
      payment method id: {paymentMethod.id}
      <ul>
        {paymentMethod.banking_cards.map((card) => (
          <Card key={card.id} card={card} />
        ))}
      </ul>
      <button
        onClick={() =>
          dispatch(
            //dispatch action with payment method id
            addCardSuccess(paymentMethod.id, {
              //the new card to be added
              id: createId(),
            })
          )
        }
      >
        Add card
      </button>
    </li>
  );
});
const App = () => {
  const paymentMethods = useSelector(selectPaymentMethods);
  return (
    <ul>
      {paymentMethods.map((paymentMethod) => (
        <PaymentMethod
          key={paymentMethod.id}
          paymentMethod={paymentMethod}
        />
      ))}
    </ul>
  );
};

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id="root"></div>

对于immer,我会使用支付方法索引,而不需要地图:

代码语言:javascript
复制
const { Provider, useDispatch, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { produce } = immer;

const createId = ((id) => () => id++)(3);

const initialState = {
  paymentMethods: [
    {
      id: 8,
      banking_cards: [
        {
          id: 1,
        },
        {
          id: 2,
        },
      ],
    },
    {
      id: 9,
      banking_cards: [
        {
          id: 1,
        },
        {
          id: 2,
        },
      ],
    },
  ],
};
//action types
const ADD_CARD_SUCCESS = 'ADD_CARD_SUCCESS';
//action creators
const addCardSuccess = (index, card) => ({
  type: ADD_CARD_SUCCESS,
  payload: { index, card },
});
const reducer = (state, { type, payload }) => {
  if (type === ADD_CARD_SUCCESS) {
    //lot less hassle using index and immer
    const { index, card } = payload;
    return produce(state, (draft) => {
      draft.paymentMethods[index].banking_cards.push(card);
    });
  }
  return state;
};
//selectors
const selectPaymentMethods = (state) =>
  state.paymentMethods;
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(() => (next) => (action) =>
      next(action)
    )
  )
);
//pure component so not re rendering when nothing changed
const Card = React.memo(function Card({ card }) {
  return <li>card: {card.id}</li>;
});
//pure component so it won't re render when nothing changes
const PaymentMethod = React.memo(function PaymentMethod({
  paymentMethod,
  index,
}) {
  const dispatch = useDispatch();
  return (
    <li>
      payment method id: {paymentMethod.id}
      <ul>
        {paymentMethod.banking_cards.map((card) => (
          <Card key={card.id} card={card} />
        ))}
      </ul>
      <button
        onClick={() =>
          dispatch(
            //dispatch action with payment method index
            addCardSuccess(index, {
              //the new card to be added
              id: createId(),
            })
          )
        }
      >
        Add card
      </button>
    </li>
  );
});
const App = () => {
  const paymentMethods = useSelector(selectPaymentMethods);
  return (
    <ul>
      {paymentMethods.map((paymentMethod, index) => (
        <PaymentMethod
          key={paymentMethod.id}
          paymentMethod={paymentMethod}
          index={index}
        />
      ))}
    </ul>
  );
};

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://unpkg.com/immer@7.0.5/dist/immer.umd.production.min.js"></script>
<div id="root"></div>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62691199

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档