Unable to Access Store and Dispatch from Redux Middleware - javascript

I am trying to create a simple Redux middleware in my React Redux Electron app that uses Thunk and connected-react-router.
In myMiddleware.js, we need to access the Redux store and dispatch function to send some actions. However, getState and dispatch are undefined as shown in the code below.
What is the correct way to access both of them in a custom Redux middleware?
Github Repo:
https://github.com/nyxynyx/accessing-store-dispatch-from-redux-middleware
middleware/myMiddleware.js
const myMiddleware = () => {
return ({ getState, dispatch }) => {
console.log(getState) // undefined
console.log(dispatch) // undefined
return next => action => {
return next(action);
}
}
}
store.js
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
import { connectRouter, routerMiddleware, push } from 'connected-react-router';
import persistState from 'redux-localstorage';
import thunk from 'redux-thunk';
import myMiddleware from './middleware/myMiddleware';
export default function configureStore(initialState, routerHistory) {
const router = routerMiddleware(routerHistory);
const actionCreators = {
push,
};
const reducers = {
router: connectRouter(routerHistory),
};
const middlewares = [myMiddleware, thunk, router];
const composeEnhancers = (() => {
const compose_ = window && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
if (process.env.NODE_ENV === 'development' && compose_) {
return compose_({ actionCreators });
}
return compose;
})();
const enhancer = composeEnhancers(applyMiddleware(...middlewares), persistState());
const rootReducer = combineReducers(reducers);
return createStore(rootReducer, initialState, enhancer);
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router';
import { createMemoryHistory } from 'history';
import routes from './routes';
import configureStore from './store';
const syncHistoryWithStore = (store, history) => {
const { router } = store.getState();
if (router && router.location) {
history.replace(router.location);
}
};
const initialState = {};
const routerHistory = createMemoryHistory();
const store = configureStore(initialState, routerHistory);
syncHistoryWithStore(store, routerHistory);
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={routerHistory}>{routes}</ConnectedRouter>
</Provider>,
document.getElementById("root")
);
Using
connected-react-router#6.8.0
react-dom#16.13.1
react-redux#7.2.0
react-router-dom#5.1.2
react-router#5.1.2
react#16.13.1
redux-localstorage#0.4.1
redux-thunk#2.3.0
redux#4.0.5
Node v14.0.0

Related

Nextjs Redux getState undefined

Hi i have simple project in Nextjs .I want to get the state of redux store but when i am trying to use store.getState it's throwing one error getState of undefined. And I have one simple vinalla javascript file i want to use getState inside that file also .How can i do that.
//store.js
import { useMemo } from "react";
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import { persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import { rootReducer } from "./reducer";
import { exampleInitialState } from "./reducer";
let store;
const persistConfig = {
key: "primary",
storage,
whitelist: ["exampleData", "count"], // place to select which state you want to persist
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
function makeStore(initialState = exampleInitialState) {
return createStore(
persistedReducer,
initialState,
composeWithDevTools(applyMiddleware())
);
}
export const initializeStore = (preloadedState) => {
let _store = store ?? makeStore(preloadedState);
// After navigating to a page with an initial Redux state, merge that state
// with the current state in the store, and create a new store
if (preloadedState && store) {
_store = makeStore({
...store.getState(),
...preloadedState,
});
// Reset the current store
store = undefined;
}
// For SSG and SSR always create a new store
if (typeof window === "undefined") return _store;
// Create the store once in the client
if (!store) store = _store;
return _store;
};
export function useStore(initialState) {
const store = useMemo(() => initializeStore(initialState), [initialState]);
return store;
}
//_app.js
import { useStore } from '../store'
import { Provider } from 'react-redux'
import { persistStore } from 'redux-persist'
import { PersistGate } from 'redux-persist/integration/react'
export default function App({ Component, pageProps }) {
const store = useStore(pageProps.initialReduxState)
const persistor = persistStore(store, {}, function () {
persistor.persist()
})
return (
<Provider store={store}>
<PersistGate loading={<div>loading</div>} persistor={persistor}>
<Component {...pageProps} />
</PersistGate>
</Provider>
)
}
vinall.js - How can i use store.getState in this file
import React from "react";
import { useStore } from "../store";
function vanilla() {
return <div>i m vanilla js file</div>;
}
export default vanilla;
//Also in this file
import { useStore } from "../store";
function simplejs() {
let state=useStore.getState();
return state.tods;
}
To access your redux store you can import the useSelector hook from react-redux and use it like so:
const yourStateProp = useSelector((state) => state.yourStateProp);
const myPersistReducer = persistReducer(persistConfig **as any**, rootReducer)
const store = createStore(myPersistReducer, applyMiddleware(sagaMiddleware));`
strong text
`It can be asserted that its type is declared for use

Can't render redux to other component reactjs

I'm trying to use redux on my current project. However, I can't use the dispatch data to another component.
Here's my code:
Authenticate.js
import { useDispatch, useSelector } from 'react-redux';
import { setLoginDetails } from 'redux/actions/loginActions';
function Authenticate() {
const [data, setData] = useState([]);
const dispatch = useDispatch();
const loginDetails = useSelector((state) => state);
const validateLogin = async() => {
const response = await.get('/api')
let responseValue = response.data.success
if(responseValue === true) {
let responseResp = JSON.parse(response.data.resp)
dispatch(setLoginDetails(responseResp.data.user))
/** here's the console logs
console.log('responseResp',responseResp)
console.log('AuthenticationOAK/responseResp.data.',responseResp.data)
console.log('AuthenticationOAK/responseResp.data.user',responseResp.data.user)
*/
window.location = '/home'
}
else{
//error
}
}
useEffect(()=>{
validateLogin();
},[])
return(
<div>Authenticating....</div>
)
}
export default Authenticate;
loginAction.js
import { ActionTypes } from '../constants/action-types';
export const setLoginDetails = (loginDetails) => {
return {
type: ActionTypes.SET_LOGIN,
payload: loginDetails,
}
}
action-types.js
export const ActionTypes = {
SET_LOGIN: 'SET_LOGIN',
}
loginReducer.js
import { ActionTypes } from '../constants/action-types';
const initialState = {
loginDetails: [],
}
export const loginReducer = (state = initialState, {type, payload}) => {
console.log('loginReducer/state', state)
console.log('loginReducer/payload',payload)
console.log('loginReducer/type', type)
console.log('loginReducer/initialState',initialState)
switch(type){
case ActionTypes.SET_LOGIN:
return {...state, loginDetails: payload}
default:
return state;
}
}
Home.js
import { useSelector } from 'react-redux';
function Home(){
const loginDetails = useSelector((state) => state.allLoginDetails.loginDetails)
const { email, userName, firstName } = loginDetails;
return(
<h1>username {userName}</h1>
)
}
export default Home;
index.js /redux/reducers/index.js
import { combineReducers } from 'redux'
import { loginReducer } from './loginReducer'
const reducers = combineReducers({
allLoginDetails: loginReducer,
});
export default reducers;
store.js
import { createStore } from 'redux'
import reducers from './index'
const store = createStore(
reducers,
{},
);
export dafault store;
Index.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
import {createStore} from 'redux'
import { Provider } from 'react-redux'
import store from '../src/redux/reducers/store'
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'));
Below are the result of console logs from Authenticate.js
screenshots of console log from loginReducer.js
Hoping that you can help me with this, I'm having a hard time on this. Tried to use hard coded value on initialState and it's rendering properly. But when I use dynamic data it's not rendering. Thank you in advance. Stay safe!
in this file: Authenticate.js
useEffect(()=>{
Authenticate(); // it must be validateLogin()?
},[])

TypeScript Redux

I started doing the typing of my redux and ran into such a problem, namely the typing of useSelector
Here is the hook I'm creating:
import {TypedUseSelectorHook, useSelector} from 'react-redux'
import {RootState} from '../store/create-reducer'
export const UseTypedSelector: TypedUseSelectorHook <RootState> = useSelector
And he returns me an error:
screen
How to solve this problem? For the second day I can't get off the ground, and using useSelector ((state: any) => state? .SESSION) is not an option.
Here is my side:
create-reducer:
import { combineReducers } from 'redux'
import { STATE } from '../session/types'
import { reducer } from '../session/reducers'
const rootReducer = (asyncReducers: object) => {
return (
combineReducers({
...asyncReducers,
[STATE]: reducer,
})
)
}
export default rootReducer
export type RootState = ReturnType<typeof rootReducer>
create-store:
import { applyMiddleware, compose, createStore } from 'redux'
import thunk from 'redux-thunk'
import persistStore from './persist-store'
import persistReducer from './persist-reducer'
const store = (initialState = {}) => {
const middlewares = [thunk]
const enhancers: Array<any> = []
const store = createStore(
persistReducer({}),
initialState,
compose(applyMiddleware(...middlewares), ...enhancers),
)
const persistor = persistStore(store)
return { store, persistor }
}
export default store
index:
export { default as createReducer } from './create-reducer'
export { default as createStore } from './create-store'
export { default as persistReducer } from './persist-reducer'
persist-reducer:
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import createReducer from './create-reducer'
const persistConfig = { key: 'myproject', storage, whitelist: ['session'] }
const reducer = (asyncReducers: any) => persistReducer(persistConfig, createReducer(asyncReducers))
export default reducer
persist-store:
import { persistStore } from 'redux-persist'
const store = (store: any) => persistStore(store, null, () => {})
export default store

No reducer provided for key {name}

I have set up my redux store and everything seems alright all imports and exports seems correct to me but I do not seem to have a valid reducer and sagas. Been stuck, what am I doing wrong?
I get this error message
I have a store with the file structure below
Store
configStore.js
index.js
import { applyMiddleware, compose, createStore } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from '../components/rootReducer';
export default function configureStore(initialState) {
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
return {
...createStore(
rootReducer,
initialState,
composeEnhancers(applyMiddleware(sagaMiddleware)),
),
runSaga: sagaMiddleware.run,
};
}
import configureStore from './configStore';
import rootSaga from '../components/rootSaga';
const store = configureStore({});
store.runSaga(rootSaga);
export default store;
rootSaga
import { all } from 'redux-saga/effects';
import planets from './planets';
export default function* rootSaga() {
yield all([
planets.sagas(),
]);
}
rootReducer
import { combineReducers } from 'redux';
import planets from './planets';
export default combineReducers({
planets: planets.reducers,
});
In my components I have
reducers.js
import { UPDATE_PLANETS, LOAD_PLANETS } from './actionTypes';
const initialState = {
isPlanetsLoading: false,
planets: [],
};
export default (state = initialState, { type, payload }) => {
switch (type) {
case LOAD_PLANETS:
return {
...state,
isPlanetsLoading: true,
};
case UPDATE_PLANETS:
return {
...state,
isPlanetsLoading: false,
planets: payload,
};
default:
return state;
}
};
Planets.js
import { List } from "antd";
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { requestPlanets } from '../actions';
const Planets = () => {
const dispatch = useDispatch();
const { planets } = useSelector(
(state) => state.planets
);
console.log(planets);
useEffect(() => {
dispatch(requestPlanets());
}, [dispatch, planets]);
// return statement
};
export default Planets;
createStore returns the store. So don't spread it. Just associate the output of createStore to an object property say store.
in index.js, destructure the configStore object { store, runSaga }
configStore
export default function configureStore(initialState) {
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
return {
store: createStore(
rootReducer,
initialState,
composeEnhancers(applyMiddleware(sagaMiddleware)),
),
runSaga: sagaMiddleware.run,
};
}
index.js
import configureStore from './configStore';
import rootSaga from '../components/rootSaga';
const { store, runSaga } = configureStore({});
runSaga(rootSaga);
export default store;

React-Redux Uncaught Error: Expected the reducer to be a function

The github repo for this project: https://github.com/leongaban/react_starwars
Expected
My basic app runs without errors, and in the chrome devtools Redux tab, I see a list of star wars characters
Results
The main index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/App'
import { createStore, applyMiddleware, compose } from 'redux'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk'
import reducer from './reducer'
import { getCharacters } from './reducer/characters/actions'
const store = createStore(reducer, compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension : f => f
));
store.dispatch(getCharacters())
const container = document.getElementById('app-container');
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, container);
My src > reducer > characters > actions.js
import { API_URL } from '../../constants'
export const SET_CHARACTERS = 'SET_CHARACTERS'
export function getCharacters() {
return dispatch => {
fetch(`${API_URL}/people`)
.then(res => res.json())
.then(res => res.results)
.then(characters =>
dispatch(setCharacters(characters))
)
}
}
export function setCharacters(characters) {
return {
type: SET_CHARACTERS,
characters
}
}
reducer > characters > index.js
import { SET_CHARACTERS } from './actions'
const initialState = [];
export default (state = initialState, action) => {
switch(action.type) {
case SET_CHARACTERS:
return action.characters;
default:
return state;
}
}
reducer > index.js
import { combineReducers } from 'redux'
import characters from './characters'
export default combineReducers({
characters
})
try
const createFinalStore = compose(
applyMiddleware(thunk)
)(createStore)
const store = createFinalStore(reducer, initialState /* or {} */);
i don't think the createStore redux api wants you to pass the middleware as the second argument. that should be the initial/preloaded state
http://redux.js.org/docs/api/createStore.html

Categories

Resources