1

I am working on a React application and I am using Redux to manage the state. I have the following code:

reducer.js

import { actionTypes } from "./actionsTypes";

const initialState = {
  items: [],
  loading: false,
  error: null,
  bookmarks: [],
  hidden: false,
  basket: [],
};

const productReducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.FETCH_PRODUCTS_BEGIN:
      return {
        ...state,
        loading: true,
        error: null,
      };

    case actionTypes.FETCH_PRODUCTS_SUCCESS:
      return {
        ...state,
        loading: false,
        items: action.payload,
      };

    case actionTypes.FETCH_PRODUCTS_FAILURE:
      return {
        ...state,
        loading: false,
        error: action.payload,
        items: [],
      };

    case actionTypes.ADD_TO_BOOKMARK:
      return {
        ...state,
        bookmarks: [...state.bookmarks, action.payload],
      };

    case actionTypes.ADD_TO_BASKET:
      return {
        ...state,
        basket: [...state.basket, action.payload],
      };

    case actionTypes.TOGGLE_HIDDEN:
      return {
        ...state,
        hidden: !state.hidden,
      };

    default:
      return state;
  }
};

export default productReducer;

actions.js

import axios from "axios";
import { actionTypes } from "./actionsTypes";

..
...
...

export const addToBookmarks = (item) => ({
  type: actionTypes.ADD_TO_BOOKMARK,
  payload: item,
});

export const addToBasket = (product) => ({
  type: actionTypes.ADD_TO_BASKET,
  payload: product,
});

axios.defaults.baseURL = "https://fakestoreapi.com";

export const fetchProducts = () => {
  return (dispatch) => {
    dispatch(fetchProductsBegin());
    try {
      return axios
        .get("https://fakestoreapi.com/Products")
        .then(({ data }) => dispatch(fetchProductsSuccess(data)));
    } catch (error) {
      dispatch(fetchProductsFailure(error));
    }
  };
};

selectors.js

import { createSelector } from "reselect";

export const selectItems = (state) => state.products; 
export const selectBookmarksProducts = createSelector(
[selectItems],
(shop) => shop.bookmarks
); 

For my reducer function, the initial state ( items ) is retrieved data from an api.

Product.js

const Product = ({ product, toggleHidden, addToBookmarks, addToBasket }) => {
  const { title, category, description, image, price } = product || {};    
  return (
    <div className="relative">
     ....
     .....
      <HeartIcon
        className={`absolute top-2 right-4 w-8 cursor-pointer ${
          bookmark ? "text-red-500" : "text-gray-500"
        }`}
        onClick={() => addToBookmarks(product)}
      />
      <CustomButton onClick={() => addToBasket(product)}>
        Add to Basket
      </CustomButton>
    </div>
  );
};

export const mapDispatchToProps = (dispatch) => ({
  addToBookmarks: (item) => dispatch(addToBookmarks(item)),
  toggleHidden: () => dispatch(toggleHidden()),
  addToBasket: (item) => dispatch(addToBasket(item)),
});

export default connect(null, mapDispatchToProps)(Product);

Note : I dispatched an action addToBookmarks and I passed product as an object After that, I want to get the bookmarks products in the bookmarksPage I don't know why I got this error TypeError: state.bookmarks is not iterable
Please can anyone help

Rayen Mehrez
  • 105
  • 1
  • 12
  • where are you getting this error? – RABI Aug 03 '21 at 13:28
  • When I bookmark a product then I visit /bookmarks page I got the error – Rayen Mehrez Aug 03 '21 at 13:30
  • I'm not sure I'd consider this a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve), so getting help here might be difficult. For one, the Selectors and the JSX you are providing aren't the most hepful, and you don't show how the reducer is connected to the store (are you using [combineReducers](https://redux.js.org/api/combinereducers)?). I'd try logging `{ state, action }` from that reducer and see when `bookmarks` is changing to a non-array. Alternatively, you could use [redux devtools](https://github.com/zalmoxisus/redux-devtools-extension). – romellem Aug 03 '21 at 13:33
  • Did you check in redux store whether the expected value is saved.. you can use redux devtools to see what is the data getting stored in store. – RABI Aug 03 '21 at 13:33
  • Everything is fine because I dispatched an async function to fetch products from an API the problem is in the bookmarks state – Rayen Mehrez Aug 03 '21 at 13:49

1 Answers1

0

I believe following change will solve the issue

case actionTypes.ADD_TO_BOOKMARK:
{
      const bookmarks = state.bookmarks;
      bookmarks.push(action.payload);
      return {
        ...state,
        bookmarks,
      };
}

RABI
  • 692
  • 2
  • 15
  • products: bookmarks: {id: 1, title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops", price: 109.95, description: "Your perfect pack for everyday use and walks in th…to 15 inches) in the padded sleeve, your everyday", category: "men's clothing", …} hidden: false items: (20) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] loading: false This is the productsReducer state I used redux-logger to log each action. I don't understand why bookmarks is an object while Initially, I set it to an empty array. – Rayen Mehrez Aug 03 '21 at 13:47
  • I changed the curly braces instead the square bracket I got the same error – Rayen Mehrez Aug 03 '21 at 13:56
  • My bad.. i have made edit in the answer... i believe this will solve the issue.. let me know – RABI Aug 03 '21 at 13:56
  • The same issue Rabeeh – Rayen Mehrez Aug 03 '21 at 14:01
  • try to console.log(bookmarks) after the push method and see what is there? – RABI Aug 03 '21 at 14:03
  • Yes I tried that this error throws TypeError: bookmarks.push is not a function – Rayen Mehrez Aug 03 '21 at 14:04
  • and what about console(state.bookmarks) before the push method? is not returning empty array? – RABI Aug 03 '21 at 14:07
  • I console.log(bookmarks) before the push method and I got a product which is an object – Rayen Mehrez Aug 03 '21 at 14:08
  • try to clear the store and do again.. in the first case of adding an item to bookmark, it must return an empty array. otherwise there is some other method which is adding a product to bookmark state which is not shown here in the code – RABI Aug 03 '21 at 14:10
  • How can I delete the redux store please ? – Rayen Mehrez Aug 03 '21 at 14:21
  • Should I create a new store or what ? – Rayen Mehrez Aug 03 '21 at 14:21
  • I got it the problem is here when I deleted the products from whitelist it works const persistConfig = { key: "root", storage, whitelist: ["products"], ==> [ ] }; – Rayen Mehrez Aug 03 '21 at 14:31