dispatching action in redux-saga is not fetching data - reactjs

I am studying redux-saga and I want to fetch data from :
https://jsonplaceholder.typicode.com/posts
and in my redux folder I have the fallowing:
(it can be checked in this github repository
https://github.com/jotasenator/redux-saga-fetching-example/tree/main/src)
\src\redux\api.js
import axios from 'axios'
export const loadPostApi = async () => {
await axios.get(`https://jsonplaceholder.typicode.com/posts`)
}
the get request to the address in question
src\redux\app.actions.js
export const loadPostStart = () => ({
type: 'LOAD_POST_START',
})
export const loadPostSuccess = (posts) => ({
type: 'LOAD_POST_SUCCESS',
payload: posts,
})
export const loadPostFail = (error) => ({
type: 'LOAD_POST_FAIL',
payload: error,
})
those are the actions functions
src\redux\app.reducer.js
const INITIAL_STATE = {
loading: false,
posts: [],
errors: null,
}
export const appReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case 'LOAD_POST_START':
return {
...state,
loading: true,
}
case 'LOAD_POST_SUCCESS':
return {
...state,
posts: action.payload,
loading: false,
}
case 'LOAD_POST_FAIL':
return {
...state,
errors: action.payload,
loading: false,
}
default:
return state;
}
}
the reducer of the fetching, updating state,
src\redux\counterReducer.js
import { types } from "./types";
const initialState = {
value: 0
}
export const counterReducer = (state = initialState, action) => {
switch (action.type) {
case types.adicionar:
return {
...state,
value: state.value + 1
}
case types.resetear:
return {
...state,
value: 0
}
case types.restar:
return {
...state,
value: state.value - 1
}
default:
return state
}
}
this is the reducer of the counter app, with different approach, types are isolated in another file
src\redux\rootReducer.js
import { combineReducers } from 'redux'
import { counterReducer } from './counterReducer'
import { appReducer } from './app.reducer'
export const rootReducer = combineReducers({
counterReducer,
appReducer
})
the rootReducer for gathering the reducers
src\redux\sagas.js
import { put, takeLatest, call } from 'redux-saga/effects'
import { loadPostApi } from './api'
import { loadPostFail, loadPostSuccess } from './app.actions'
export function* onLoadPostStartAsync() {
try {
const response = yield call(loadPostApi)
yield put(loadPostSuccess(response.data))
} catch (error) {
yield put(loadPostFail(error))
}
}
export function* onLoadPost() {
yield takeLatest('LOAD_POST_START', onLoadPostStartAsync)
}
export default function* rootSaga() {
yield ([
onLoadPost(),
])
}
saga onLoadPostStartAsync called by saga onLoadPost inside rootSaga
src\redux\store.js
import { applyMiddleware, compose, createStore } from "redux";
import createSagaMiddleware from 'redux-saga'
import { rootReducer } from "./rootReducer";
import rootSaga from "./sagas";
const sagaMiddleware = createSagaMiddleware()
const composeEnhancers = (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose
const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware))
export const store = createStore(rootReducer, enhancer)
sagaMiddleware.run(rootSaga)
this is the store with the redux_devtool_extension, the reducers, and running rootSaga
src\redux\types.js
export const types = {
adicionar: 'ADICIONAR',
resetear: 'RESETEAR',
restar: 'RESTAR'
}
those are the types of the counterApp reducer
src\Counter.js
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
export const Counter = () => {
const dispatch = useDispatch()
const { value } = useSelector(state => state.counterReducer)
const handleAdicionar = () => {
dispatch({ type: 'ADICIONAR' })
}
const handleResetear = () => {
(value !== 0) && dispatch({ type: 'RESETEAR' })
}
const handleRestar = () => {
dispatch({ type: 'RESTAR' })
}
console.log(value)
return (
<div>
<button onClick={handleAdicionar}>Adicionar</button>
{' '}
<button onClick={handleResetear}>Resetear</button>
{' '}
<button onClick={handleRestar}>Restar</button>
<hr />
</div>
)
}
this is the Counter component, it works ok
src\Fetching.js
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { loadPostStart } from './redux/app.actions'
export const Fetching = () => {
const dispatch = useDispatch()
const fetchPost = () => {
dispatch(loadPostStart())
}
const state = useSelector(state => state.appReducer)
console.log(state)
return (
<>
<h1>Fetching from https://jsonplaceholder.typicode.com</h1>
<button onClick={fetchPost}>Fetching</button>
{
!state.loading && state.posts.map((post) => (
<li key={post.id}><h2>{post.title}</h2></li>
))
}
</>
)
}
the Fetching component click on the button calls fetchPost function who dispatch loadPostStart() function which is the same of dispatching {type: 'LOAD_POST_START'}, but nothing happens here when clicking, not fetch nothing from here https://jsonplaceholder.typicode.com/posts
src\index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { store } from './redux/store';
import { Provider } from "react-redux";
import { Unificator } from './Unificator';
ReactDOM.render(
<Provider store={store}>
<Unificator />
</Provider>,
document.getElementById('root')
);
component Unificator has Counter and Fetching component
src\Unificator.js
import React from 'react'
import { Counter } from './Counter'
import { Fetching } from './Fetching'
export const Unificator = () => {
return (
<div>
<Counter />
<Fetching />
</div>
)
}
as you can see is about of two reducers, one is the famous counter, and the another one is the fetching issue, do not know what is happening that is not fetching the data
obviously, i am doing something wrong here...don t see where

Axio returns promise, You need to capture that and return. Please try replacing below code.
export const loadPostApi = async () => {
await axios.get(`https://jsonplaceholder.typicode.com/posts`)
.then((response) => {
console.log('Response', response);
return response;
})
.catch((error) => {
console.log('error', error);
})
}

Related

Redux-Saga: TypeError: Cannot read properties of undefined (reading 'data')

I was trying to run my Redux app with redux-saga.
Basically on my store.js I have the following codes:
import { applyMiddleware, createStore } from "redux";
import createSagaMiddleware from "redux-saga";
import logger from "redux-logger";
import rootReducer from "./reducers/rootReducer";
import rootSaga from "./sagas/userSagas";
const sagaMiddleware = createSagaMiddleware();
const middleware = [sagaMiddleware];
if (process.env_NODE_ENV === "development") {
middleware.push(logger);
}
const store = createStore(rootReducer, applyMiddleware(...middleware));
sagaMiddleware.run(rootSaga);
export default store;
My usersApi.js looks something like this:
import axios from "axios";
export const loadUsersApi = async () => {
await axios.get("http://localhost:5000/users");
};
And here is my userSagas:
import * as type from "../actionType";
import {
take,
takeEvery,
takeLatest,
put,
all,
delay,
fork,
call,
} from "redux-saga/effects";
import { loadUsersSuccess, loadUsersError } from "../actions/userAction";
import { loadUsersApi } from "../services/userApi";
export function* onLoadUsersStartAsync() {
try {
const response = yield call(loadUsersApi);
if (response.status === 200) {
yield delay(500);
yield put(loadUsersSuccess(response.data));
}
} catch (error) {
yield put(loadUsersError(error.response.data));
}
}
export function* onLoadUsers() {
yield takeEvery(type.LOAD_USERS_START, onLoadUsersStartAsync);
}
const userSagas = [fork(onLoadUsers)];
export default function* rootSaga() {
yield all([...userSagas]);
}
When I run this on my HomePage.js file where I load and dispatch the data:
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { loadUsersStart } from "../redux/actions/userAction";
export default function HomePage() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(loadUsersStart());
}, [dispatch]);
return (
<div>
<h1>Home</h1>
</div>
);
}
It gave me this error:
[HMR] Waiting for update signal from WDS...
index.js:1 TypeError: Cannot read properties of undefined (reading 'data')
at onLoadUsersStartAsync (userSagas.js:25)
at onLoadUsersStartAsync.next (<anonymous>)
at next (redux-saga-core.esm.js:1157)
at currCb (redux-saga-core.esm.js:1251)
index.js:1 The above error occurred in task onLoadUsersStartAsync
created by takeEvery(LOAD_USERS_START, onLoadUsersStartAsync)
created by onLoadUsers
created by rootSaga
Tasks cancelled due to error:
takeEvery(LOAD_USERS_START, onLoadUsersStartAsync)
I am not sure what's causing this error, but even the logger of my app doesn't even show the actions being dispatched.
Any idea how can I fix this issue?
You need to return promise from
export const loadUsersApi = () => {
return axios.get("http://localhost:5000/users");
};
Maybe next time try to use typescript. It will prevent You from similar mistakes
Alternatively, you can build your redux without using redux-saga.
This is how I usually set them up:-
A. Reducer
/slices/auth.js
import { createSlice } from '#reduxjs/toolkit'
const initialState = {
users: [],
loading: false,
success: false,
error: false,
message: ''
}
export const usersSlice = createSlice({
name: 'users',
initialState,
// // The `reducers` field lets us define reducers and generate associated actions
reducers: {
setUsers: (state, action) => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.users = action.payload
},
setLoading: (state, action) => {
state.loading = action.payload
},
setSuccess: (state, action) => {
state.success = action.payload.status
state.message = action.payload.message
},
setError: (state, action) => {
state.error = action.payload.status
state.message = action.payload.message
}
}
})
export const { setUsers, setLoading, setSuccess, setError, setMessage } = usersSlice.actions;
// The function below is called a selector and allows us to select a value from
// the state. Selectors can also be defined inline where they're used instead of
// in the slice file. For example: `useSelector((state: RootState) => state.counter.value)`
export const selectUsers = (state) => state.users.users
export const selectLoading = (state) => state.users.loading
export const selectSuccess = (state) => state.users.success
export const selectError = (state) => state.users.error
export const selectMessage = (state) => state.users.message
export default usersSlice.reducer;
B. Store
store.js
import { configureStore, getDefaultMiddleware } from '#reduxjs/toolkit'
import usersReducer from '../slices/users'
export const store = configureStore({
reducer: {
users: usersReducer
},
middleware: getDefaultMiddleware({
serializableCheck: false
})
})
C. App Component
import { Provider } from 'react-redux'
import { store } from '../app/store'
export default function App() {
return {
<>
<Provider store={store}>
{/* your content... */}
</Provider>
</>
}
}
D. Component (where you use the redux)
import { useContext, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { selectUsers, selectLoading, selectSuccess, selectError, selectMessage, setUsers, setLoading, setSuccess, setError } from '../slices/users'
import axios from 'axios'
export default function HomePage() {
const dispatch = useDispatch()
const users = useSelector(selectUser)
const loading = useSelector(selectLoading)
const success = useSelector(selectSuccess)
const error = useSelector(selectorError)
const message = useSelector(selectorMessage)
useEffect(() => {
async function init() {
dispatch(setLoading(true))
const response = await axios.get('http://localhost:5000/users')
if(response?.status == 200) {
dispatch(setUsers(response?.data?.data))
dispatch(setSuccess({ status: true, message: 'Successfully get users data.' }))
} else {
dispatch(setError({ status: true, message: 'Failed to get data.' }))
}
dispatch(setLoading(false))
}
return init()
}, [])
return {
<>
{user}
</>
}
}

Nextjs - await store.dispatch Cannot read property 'dispatch' of undefined

I'm new to React, Redux and have been following tutorials on the topic. I'm come across a lot of issues that I've been able to resolve but I've come across an issue I can't resolve. I set up store, and can even view it through Chrome's Redux Tools and it show correctly, however when I try and dispatch to the Store, I always get a Cannot read property 'dispatch' of undefined error. I have followed numerous tutorials letter for letter, and am still stuck with the same error message.
Index.Js
import Layout from '../components/layout/Layout';
import Home from '../components/Home';
import { getRooms } from '../redux/actions/roomActions';
import { wrapper } from '../redux/store';
export default function Index() {
return (
<Layout>
<Home />
</Layout>
);
}
export const getServerSideProps = wrapper.getServerSideProps(
async ({ req, store }) => {
await store.dispatch(getRooms(req));
}
);
roomConstants.js
export const ALL_ROOMS_SUCCESS = 'ALL_ROOMS_SUCCESS';
export const ALL_ROOMS_FAIL = 'ALL_ROOMS_FAIL';
export const CLEAR_ERRORS = 'CLEAR_ERRORS';
reducer.js
import { combineReducers } from 'redux';
import { allRoomsReducer } from './roomReducers';
const reducer = combineReducers({
allRooms: allRoomsReducer,
});
export default reducer;
Store.js
import { createStore, applyMiddleware } from 'redux';
import { HYDRATE, createWrapper } from 'next-redux-wrapper';
import thunkMiddleware from 'redux-thunk';
import reducers from './reducers/reducers';
const bindMiddleware = (middleware) => {
if (process.env.NODE_ENV !== 'production') {
const { composeWithDevTools } = require('redux-devtools-extension');
return composeWithDevTools(applyMiddleware(...middleware));
}
return applyMiddleware(...middleware);
};
const reducer = (state, action) => {
if (action.type === HYDRATE) {
const nextState = {
...state,
...action.payload,
};
return nextState;
} else {
return reducers(state, action);
}
};
const initStore = () => {
return createStore(reducer, bindMiddleware([thunkMiddleware]));
};
export const wrapper = createWrapper(initStore);
roomReducer.js
import {
ALL_ROOMS_SUCCESS,
ALL_ROOMS_FAIL,
CLEAR_ERRORS,
} from '../constants/roomConstants';
// All rooms reducer
export const allRoomsReducer = (state = { rooms: [] }, action) => {
switch (action.type) {
case ALL_ROOMS_SUCCESS:
return {
roomsCount: action.payload.roomsCount,
resPerPage: action.payload.resPerPage,
filteredRoomsCount: action.payload.filteredRoomsCount,
rooms: action.payload.rooms,
};
case ALL_ROOMS_FAIL:
return {
error: action.payload,
};
case CLEAR_ERRORS:
return {
...state,
error: null,
};
default:
return state;
}
};
roomAcion.js
import axios from 'axios';
import absoluteUrl from 'next-absolute-url';
import {
ALL_ROOMS_SUCCESS,
ALL_ROOMS_FAIL,
CLEAR_ERRORS,
} from '../constants/roomConstants';
//Clear errors
export const clearErrors = () => async (dispatch) => {
return dispatch({
type: CLEAR_ERRORS,
});
};
// Get all rooms
export const getRooms = (req) => async (dispatch) => {
try {
const { origin } = absoluteUrl(req);
const { data } = await axios.get(`${origin}/api/rooms`);
dispatch({
type: ALL_ROOMS_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: ALL_ROOMS_FAIL,
payload: error.response.data.message,
});
}
};
in index.js, your getServerSideProps function should read this;
export const getServerSideProps = wrapper.getServerSideProps((store) => async ({ req }) => {
await store.dispatch(getRooms(req));})
Use the old version of next-redux-wrapper like 6.0.2

Why my action is not triggering in the reducer?

does anyone knows why nothing happens when the button is clicked?
im trying to fetch the movielist from the server when the button is clicked but it doesnt even shows that the action is working the way i expected to be.
my react index js
import React from 'react';
import { connect } from 'react-redux';
import { getMovies } from '../../actions/movieActions';
const Home = ({ movie }) => {
const handleClick = () => {
getMovies();
};
return (
<div>
<button onClick={() => handleClick()}>Get Movies</button>
</div>
);
};
const mapStateToProps = state => ({
movie: state.movie.movies
});
export default connect(mapStateToProps, { getMovies })(Home);
my rootReducer
import { combineReducers } from 'redux';
import movieReducer from './movieReducer';
export default combineReducers({
movie: movieReducer
// log is what we are calling our state
});
my movie reducer
import { GET_MOVIES } from '../actions/types';
const initialState = {
movies: null
};
export default (state = initialState, action) => {
switch (action.type) {
case GET_MOVIES:
return {
...state,
movies: action.payload
};
default:
return state;
}
};
my movie actions
import { GET_MOVIES } from './types';
// get movies from server
export const getMovies = () => async dispatch => {
try {
const res = await fetch('http://localhost:5000/api/movies');
const data = await res.json();
dispatch({
type: GET_MOVIES,
payload: data
});
} catch (error) {
console.log(error);
}
};
my types.js
export const GET_MOVIES = 'GET_MOVIES';
my store.js
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
Your error is in calling the action directly, instead of the connected getMovies prop here:
const handleClick = () => {
getMovies();
};
Should be:
const handleClick = () => {
this.props.getMovies();
};

Actions must be plain objects. Use custom middleware for async actions Saga thunk I do have so far in my store

The problem is:
I'm trying to use redux-saga in my react app, but i still has this error: Actions must be plain objects. Use custom middleware for async actions. Code it seems correct but no idea why gives that error. I'll be glad for all the help. I'm fighting with it for about two days and still doesn't have a solution. I tried to look up, but I still have this error.
action...
import { GET_DISTRICTS} from '../../constants';
const getAdres = async (url) => {
let response = await fetch(url);
let data = await response.json();
let list = [];
data.AdresList.Adresler.Adres.forEach((item) => {
console.info(item);
list.push({
label: item.ADI,
value: item.ID
});
});
return list;
};
export const actions = {
handleGetDistrictsData: async () => {
let districts = await getAdres(`url is here`);
return {
type: GET_DISTRICTS,
payload: districts
};
},
reducer...
import { GET_DISTRICTS } from '../../constants';
export const initialState = {
districts: [],
quarters: [],
streets: [],
doors: [],
districtSelected: false,
districtSelectedID: null,
quarterSelected: false,
quarterSelectedID: null,
streetSelected: false,
streetSelectedID: null,
doorSelected: false,
doorSelectedID: null
};
export default (state = initialState, action) => {
switch (action.type) {
case GET_DISTRICTS:
return {
...state,
districts: action.payload
};
default:
return state;
}
};
component...
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { actions as addressActions } from '../../../../redux/actions/address';
import Select from 'react-select';
const Districts = (props) => {
let [ fetchedData, setFetchedData ] = useState(false);
useEffect(() => {
props.handleGetDistrictsData();
setFetchedData(true);
});
return (
<React.Fragment>
<Select
name='adresSelect'
options={props.address.districts}
onChange={props.handleDistrictChange}
placeholder='Please Select'
/>
</React.Fragment>
);
};
const mapStateToProps = (state) => ({
address: state.address
});
const mapDispatchToProps = function(dispatch) {
return bindActionCreators({ ...addressActions }, dispatch);
};
export default connect(mapStateToProps, mapDispatchToProps)(Districts);
-------------
import React from 'react';
import Districts from './Districts';
const AddressSearchWidget = (props) => {
return (
<React.Fragment>
<Districts />
</React.Fragment>
);
};
export default AddressSearchWidget
store...
import { applyMiddleware, combineReducers, compose, createStore } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootSaga from './sagas/index';
import * as reducers from './';
export function initStore() {
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const rootReducer = combineReducers(reducers);
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, composeEnhancer(applyMiddleware(sagaMiddleware)));
// Run sagas
sagaMiddleware.run(rootSaga);
return store;
}
handleGetDistrictsData returns a promise (all async functions return promises). You cannot dispatch a promise in plain redux saga, and redux-saga does not change this. Instead, dispatch a normal action, and have that action run a saga. The saga can then do async things, and when it's done dispatch another action. The reducer listens only for that second action.
// Actions:
export const getDistrictsData = () => ({
type: GET_DISTRICTS,
})
export const districtsDataSuccess = (districts) => ({
type: DISTRICTS_DATA_SUCCESS,
payload: districts
})
// Sagas:
export function* watchGetDistricts () {
takeEvery(GET_DISTRICTS, getDistricts);
}
function* getDistricts() {
let response = yield fetch(url);
let data = yield response.json();
let list = [];
data.AdresList.Adresler.Adres.forEach((item) => {
console.info(item);
list.push({
label: item.ADI,
value: item.ID
});
});
yield put(districtsDataSuccess(list));
}
// reducer:
export default (state = initialState, action) => {
switch (action.type) {
case DISTRICTS_DATA_SUCCESS:
return {
...state,
districts: action.payload
};
default:
return state;
}
};

'dispatch' is not defined - mapDispatchToProps not passing through Router

I am getting a dispatch is not defined error from 'shopfront' code. I believe it is because i'm not passing the properties down to the next level but I'm not sure if that is correct or not. I want to be able to pass the dispatch function through to the product.actions code correctly.
I have tried to narrow down the problem as much as possible by removing unnecessary code. I have a user reducer that is working correctly but I don't know why this product reducer isn't
// products.reducer
const initialState = {
products: null,
error: null
};
const ProductReducer = (state = initialState, action) => {
let newState = null;
switch(action.type){
case "GET_ALL_PRODUCTS": newState = {
...state,
products: action.products
};
return newState;
case "GET_ALL_PRODUCTS_FAIL": newState = {
...state,
error: action.error
};
return newState;
default: return state;
}
};
export default ProductReducer;
// index
import React from "react";
import ReactDOM from "react-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import { register } from "./serviceWorker";
import { createStore, combineReducers, applyMiddleware, compose } from "redux";
import { Provider } from "react-redux";
import thunk from "redux-thunk";
import UserReducer from "./store/reducers/users.reducers";
import ProductReducer from "./store/reducers/products.reducer";
import "./index.css";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
const appReducer = combineReducers({
usersRed: UserReducer,
productsRed: ProductReducer
});
const logger = (store) => {
return next => {
return action => {
console.log("Middleware dispatching ");
console.log(action);
const result = next(action);
console.log("Middleware next state ");
console.log(store.getState());
return result;
};
};
};
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const appStore = createStore(appReducer, composeEnhancers(applyMiddleware(logger, thunk)));
const app = (
<BrowserRouter>
<Provider store={appStore}>
<App />
</Provider>
</BrowserRouter>
);
ReactDOM.render(app, document.getElementById("root"));
register();
// shopfront
import React, { Component } from "react";
import { Container, Row, Col, InputGroup, InputGroupAddon, Button } from "reactstrap";
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import { Alert } from "reactstrap";
import * as actionMethods from "../../store/actions/index.actions";
import Product from "../../components/Product/Product";
class Shopfront extends Component {
state = {
onAlert: false,
internalError: null
};
componentDidMount() {
this.props.loadAllProducts(5);
console.log("component_did_mount_run")
}
render() {
let ProductsList = <h1>No Products Yet!</h1>;
if (this.props.products !== null) {
ProductsList = this.props.products.map(Product => {
return <Product
key={Product.id}
title={Product.name}
excerpt={Product.description}
medialink={Product.permalink}
ProductId={Product.id}
/>;
});
}
return (
<Container>
{ProductsList}
</Container>
);
}
};
const mapStateToProps = (state) => {
return {
products: state.productsRed.products,
error: state.productsRed.error
};
};
const mapDispatchToProps = (dispatch) => {
return {
loadAllProducts: (perpage) => { dispatch(actionMethods.loadAllProducts(perpage)) }
};
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Shopfront));
// index.actions
export {
loadAllProducts
} from "./product.actions";
// product.actions
import wcapi from "../../axios-wp";
export const loadAllProducts = (perpage) => {
wcapi.get("products", {
per_page: perpage,
})
.then((response) => {
// Successful request
let productsRes = response.data;
dispatch({ type: "GET_ALL_PRODUCTS", products: productsRes });
})
.catch((err) => {
// Invalid request, for 4xx and 5xx statuses
dispatch({ type: "GET_ALL_PRODUCTS_FAIL", error: err });
})
}
Thank you for your help!
it is because you are not returning dispatch from your loadAllProducts action
/ product.actions
import wcapi from "../../axios-wp";
export const loadAllProducts = (perpage) => (dispatch) => { //make this change
wcapi.get("products", {
per_page: perpage,
})
.then((response) => {
// Successful request
let productsRes = response.data;
dispatch({ type: "GET_ALL_PRODUCTS", products: productsRes });
})
.catch((err) => {
// Invalid request, for 4xx and 5xx statuses
dispatch({ type: "GET_ALL_PRODUCTS_FAIL", error: err });
})
}
I have ever faced such this issue before. Then I used return dispatch => {} like this:
export const loadAllProducts = perpage => {
return dispatch => {
wcapi.get("products", {
per_page: perpage,
})
.then((response) => {
// Successful request
let productsRes = response.data;
dispatch({ type: "GET_ALL_PRODUCTS", products: productsRes });
})
.catch((err) => {
// Invalid request, for 4xx and 5xx statuses
dispatch({ type: "GET_ALL_PRODUCTS_FAIL", error: err });
})
}
}

Resources