There is problem in setting redux store!
It cannot read that state.dataValue.data, says DataSlice is undefined.
Also in Redux Devtool no store have been setup
File: store.js
import rootReducer from "./slices";
import thunk from "redux-thunk";
import { configureStore } from "#reduxjs/toolkit"
const store = configureStore({ reducer: rootReducer, middleware: [thunk] });
export default store;
File2: slice/dataSlice.js
import { combineReducers } from 'redux';
import { dataSlice } from './dataSlice'
export default combineReducers({ dataSlice: dataSlice.reducer });
File3
import { createSlice } from "#reduxjs/toolkit";
import store from '../store'
const initialState = {
data: [],
};
const dataSlice = createSlice({
name: "dataSlice",
initialState,
reducers: {
setData(state, action) {
const { data } = action.payload;
state.data = data.map((item) => item);
},
}
});
export const {
setData,
} = dataSlice.actions;
export default dataSlice.reducer
File4 inventory.jsx
import {
setData,
} from "../../slices/dataSlice";
const Inventory = (props) => {
const dispatch = useDispatch();
const { data } = useSelector((state) => {
return {
data: state.dataSlice.data,
};
});
It showing that dataValue is undefined,
I am using React-Toolkit
Related
I have a react app that was working until I converted over to a nextjs app. The axios call is being made, the data is being returned but not being stored(the selectors are showing undefined). I suspect it is a setup issue in the conversion.
The call which works:
React.useEffect(() => {
dispatch(fetchCoinsByMarketCap()); // coin gecko
}, [dispatch]);
The slice. I am logging correct data and status in my fetchCoinsByMarketCap.fulfilled case:
import axios from "axios";
import { createAsyncThunk, createSlice } from "#reduxjs/toolkit";
import { coinGecko } from "../../url/urlList";
const initialState = {
coinsMCap: [],
status: "idle",
error: null,
};
export const fetchCoinsByMarketCap = createAsyncThunk(
"coinsByMarketCap/fetchCoinsByMarketCap",
async () => {
const res = await coinGecko.get(
`/coins/markets/?
vs_currency=usd&order=market_cap_desc&per_page=50&page=1&sparkline=false`
);
return res.data;
}
);
export const marketCapSlice = createSlice({
name: "coinsByMarketCap",
initialState,
reducers: {
updateCoinsMcapState: (state, action) => {
Object.assign(state, action.payload);
},
},
extraReducers(builder) {
builder
.addCase(fetchCoinsByMarketCap.pending, (state) => {
state.status = "loading";
})
.addCase(fetchCoinsByMarketCap.fulfilled, (state, action) => {
state.coinsMCap = action.payload;
state.status = "succeeded";
console.log("sc: ", state.coinsMCap);
console.log("ss: ", state.status);
})
.addCase(fetchCoinsByMarketCap.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message;
});
},
});
export const { updateCoinsMcapState } = marketCapSlice.actions;
export default marketCapSlice.reducer;
My store:
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import { createWrapper } from "next-redux-wrapper";
import reducer from "./rootReducer";
const middleware = [thunk];
const makeStore = () =>
createStore(reducer, compose(applyMiddleware(...middleware)));
export const wrapper = createWrapper(makeStore);
The next _app file which has the wrapper.withRedux export:
import React from "react";
import { wrapper } from "../redux/store";
const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />;
export default wrapper.withRedux(MyApp);
The root reducer:
import { combineReducers } from "redux";
import marketCapReducer from "./slices/marketCapSlice";
const reducer = combineReducers({
coinsByMarketCap: marketCapReducer,
});
export default reducer;
The selector file:
// marketCapSlice selectors
export const selectCoinsMCap = (state) => state.coinsByMarketCap.coinsMCap;
export const selectCoinsMCapStatus = (state) => state.coinsByMarketCap.status;
export const selectCoinsMCapError = (state) => state.coinsByMarketCap.error;
These selectors should have data after the axios call, but they don't. Again bear in mind that this used to work before I tried to convert it to next and the only thing I changed was the store and the _app.js files. The old store without next was very simple:
import { configureStore } from "#reduxjs/toolkit";
import reducer from "./rootReducer";
const store = configureStore({ reducer });
export default store;
And the standard provider setup in the old index:
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
Maybe one of you nextjs experts can help me.
A reducer is supposed to return the updated state, as far as I know. It seems to me like you may have forgotten to return a value here:
reducers: {
updateCoinsMcapState: (state, action) => {
Object.assign(state, action.payload);
},
},
Should it be something like this?
reducers: {
updateCoinsMcapState: (state, action) => {
return Object.assign(state, action.payload);
},
},
Here is the store setup that fixed it:
import { configureStore } from "#reduxjs/toolkit";
import { applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import { createWrapper } from "next-redux-wrapper";
import reducer from "./rootReducer";
const middleware = [thunk];
const makeStore = () =>
configureStore({ reducer }, compose(applyMiddleware(...middleware)));
export const wrapper = createWrapper(makeStore);
I used configureStore instead of createStore and enclosed reducer in curly braces.
I am tried to use saga-toolkit package to create saga action but getting some error while dispatching, although I went to official documentation of saga-toolkit npm package but something is missing over there i think and I am not able to figure out what going wrong. This is official documentation link https://npm.io/package/saga-toolkit
And I wanted to pass some argument while dispatching the action but getting error in console like
"Actions must be plain objects. Use custom middleware for async actions."
saga-toolkit provide createSagaAction which is resposibe for creating saga action but I am still get the above during dispatching
dataSlice.js
import { createSlice } from "#reduxjs/toolkit";
import { createSagaAction } from "saga-toolkit";
export const fetchData = createSagaAction("data/fetchData");
const dataSlice = createSlice({
name: "data",
initialState: {
data: [],
error: null,
loading: false,
},
extraReducers: {
[fetchData.pending]: (state) => {
state.loading = true;
},
[fetchData.fulfilled]: (state, action) => {
state.loading = false;
state.data = action.payload;
},
[fetchData.rejected]: (state, action) => {
state.loading = false;
state.error = action.payload;
},
},
});
export default dataSlice.reducer;
dataSagas.js
import { put, call, fork } from "redux-saga/effects";
import { takeLatestAsync, putAsync } from "saga-toolkit";
import * as actions from "./feature/dataSlice";
import { getDataApi } from "./api";
function* onLoadData({payload}) {
const result = yield call(getDataApi, payload);
return result;
}
function* onLoadData() {
yield takeLatestAsync(actions.fetchData.type, onLoadDataAsync);
}
export const dataSagas = [fork(onLoadData)];
rootSaga.js
import { all } from "redux-saga/effects";
import { dataSagas } from "./dataSagas";
export default function* rootSaga() {
yield all([...dataSagas]);
}
store.js
import { configureStore } from "#reduxjs/toolkit";
import createSagaMiddleware from "redux-saga";
import DataReducer from "./feature/dataSlice";
import rootSaga from "./rootSaga";
const sagaMiddleware = createSagaMiddleware();
const store = configureStore({
reducer: {
data: DataReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ thunk: false }).concat(sagaMiddleware),
});
sagaMiddleware.run(rootSaga);
export default store;
App.js
import { useEffect } from "react";
import logo from "./logo.svg";
import "./App.css";
import { useDispatch } from "react-redux";
import { fetchData } from "./redux/feature/dataSlice";
function App() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchData());
}, []);
return (
<div className="App">
<h2>Calling API using Saga-toolkit</h2>
</div>
);
}
export default App;
./src/app/store.js
Module not found: Can't resolve '../features/movie/movieSlice' in 'C:\Users\user\diseny-plus-clone\src\app'
so please tell me how to rectify this problem
this is the code of the file having error
import { configureStore } from "#reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";
import movieReducer from "../features/movie/movieSlice";
export const store = configureStore({
reducer: {
movie: movieReducer,
},
});
next is the code of the file through which i have imported
import { createSlice } from "#reduxjs/toolkit";
const initialState = {
movies: [],
};
const movieSlice = createSlice({
name: "movie",
initialState,
reducers: {
setMovies: (state, action) => {
state.movies = action.payload;
},
},
});
export const { setMovies } = movieSlice.actions;
export const selectMovies = (state) => state.movie.movies;
export default movieSlice.reducer();
please help me out
The path to access to movieSlice file is wrong, the correct path is ../features/counter/movie/movieSlice.
import { configureStore } from "#reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";
import movieReducer from "../features/counter/movie/movieSlice";
export const store = configureStore({
reducer: {
movie: movieReducer,
},
});
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();
};
I'm calling the action requestLoadOrders to fetch the orders I need. I'm dispatching with type: REQUEST and afterwards with SUCCESS or FAILURE. The fetch succeeded because my orders are in the payload in the redux dev-tools, but the action that I receive in my reducer is ##redux/PROBE_UNKNOWN_ACTION_z.r.p.l.z. I found a thread about this here, however I can't seem to find what I'm doing wrong?
actions.js
import {
LOAD_ORDERS_REQUEST,
LOAD_ORDERS_SUCCESS,
LOAD_ORDERS_FAILURE
} from './constants';
import { fetchOrders } from '../../api';
export const requestLoadOrders = () => {
return (dispatch, getState) => {
dispatch({ type: LOAD_ORDERS_REQUEST });
fetchOrders().then(orders => {
dispatch({ type: LOAD_ORDERS_SUCCESS, payload: orders });
}).catch(error => {
console.error(error);
dispatch({ type: LOAD_ORDERS_FAILURE, payload: error });
});
};
};
reducer.js
import {
LOAD_ORDERS_REQUEST,
LOAD_ORDERS_SUCCESS,
LOAD_ORDERS_FAILURE
} from './constants';
const initialState = {
orders: []
};
const orderReducer = ( state = initialState, { payload, type }) => {
switch (type) {
case LOAD_ORDERS_REQUEST :
return state;
case LOAD_ORDERS_SUCCESS :
return { ...state, orders: payload};
case LOAD_ORDERS_FAILURE :
return { ...state, error: payload.error};
default :
return state;
}
};
export default orderReducer;
My actions get dispatched correctly, but I suppose there's a problem with the reducer receiving its data. Therefor I also added my store and combined reducers files.
store.js
import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import createHistory from 'history/createBrowserHistory';
import thunk from 'redux-thunk';
import makeRootReducer from './reducers';
export const history = createHistory();
const initialState = {}
const enhancers = [];
const middleware = [ routerMiddleware(history), thunk ];
if (process.env.NODE_ENV === 'development') {
const devToolsExtension = window.devToolsExtension;
if (typeof devToolsExtension === 'function') {
enhancers.push(devToolsExtension());
}
}
const composedEnhancers = compose(
applyMiddleware(...middleware),
...enhancers
);
const store = createStore(
makeRootReducer,
initialState,
composedEnhancers
);
export default store;
reducers.js
import { combineReducers } from 'redux';
import orderReducer from '../modules/Order/reducer';
export const makeRootReducer = asyncReducers => {
return combineReducers({
order: orderReducer,
...asyncReducers
});
}
export default makeRootReducer;
I found my mistake. I should execute the makeRootReducer function by adding the brackets after the word in createStore().
Updated the createStore() part of store.js to:
const store = createStore(
makeRootReducer(),
initialState,
composedEnhancers
);
was the fix.