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
Related
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()?
},[])
I'm using redux with gatsby by installing these packages :
react react-redux gatsby-plugin-react-redux
This is store.js file :
import { createStore } from 'redux';
import { reducer } from './reducer';
export default (preloadedState) => {
return createStore(reducer, preloadedState);
};
gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-plugin-react-redux`,
options: {
pathToCreateStoreModule: './src/redux/store',
cleanupOnClient: false
}
}
]
};
I've set cleanupOnClient to false but still when I refresh the page , the state is still the old version and it has not been persisted.
How can I persist redux state changes with gatsby ?
I added redux-persist to gatsby-plugin-react-redux, you can find it here:
https://www.npmjs.com/package/gatsby-plugin-react-redux-persist
it's the first release but seems to work :)
edit:
I see that redux-persist goes to timeout during rehydratation when using preloadedState, I don't know if it happens to you too, btw you can skip it:
export default () => {
const store = createStore(
persistedReducer,
{}, // initial state
);
const persistor = persistStore(store);
return { store, persistor };
}
I like the idea behind the persist plugin, but I found that with the createStore composition, it was easy to cause issues for other libraries wanting access to the store.
Instead I added redux-persist to my existing gatsby-plugin-react-redux setup:
createStore.js
import { compose, createStore } from 'redux'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import initialState from './initialState'
import rootReducer from './rootReducer'
const persistedReducer = persistReducer({
key: 'root',
storage
}, rootReducer);
const composeEnhancers = (typeof window === 'object') ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : undefined
const store = () => {
return createStore(
persistedReducer,
initialState,
composeEnhancers ? composeEnhancers() : compose
);
}
gatsby-browser.js wrapper
import React from 'react'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
import { persistStore } from 'redux-persist'
import createStore from './src/state/createStore'
export const wrapRootElement = ({ element, props }) => {
const store = createStore()
const persistor = persistStore(store)
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
{element}
</PersistGate>
</Provider>
)
}
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
I am creating an app which fetches the list of cities entered by a user and their respective weather using openweather API. I want the cities, as a result, to remain after I refresh the page. I know how to persist the data using browser localStorage API. But I don't know how to persist it through a middleware and pass it to the provider.
Below is my main Index.js file-:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from 'redux-promise';
import App from './components/app';
import reducers from './reducers';
import {loadState,saveState} from './localStorage';
const persistedState=loadState();
const store=createStore(persistedState);
store.subscribe(()=>{
store.getState()
});
const createStoreWithMiddleware =
applyMiddleware(ReduxPromise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<App />
</Provider>
, document.querySelector('.container-fluid'));
This is the localStorage.js file-:
export const loadState=()=>{
try{
const serializedState=localStorage.getItem('state');
if(serializedState===null){
return undefined;
}
return JSON.parse(serializedState);
}catch(err){
return undefined;
}
};
export const saveState=(state)=>{
try {
const serializedState=JSON.stringify(state);
localStorage.setItem('state',serializedState);
}catch(err){
console.log(err);
}};
I have written the reducer in different files in reducers folder.
reducers/index.js -:
import { combineReducers } from 'redux';
import WeatherReducer from './reducer_weather';
const rootReducer = combineReducers({
weather:WeatherReducer
});
export default rootReducer;
and another reducer in
reducers/reducer_weather.js -:
import {FETCH_WEATHER} from '../actions/index';
import {DELETECITY} from '../actions/deleterow';
export default function(state=[],action){
switch(action.type){
case FETCH_WEATHER:
console.log([action.payload.data, ...state]);
return [action.payload.data, ...state];
case DELETECITY:
console.log([...state].filter((weather)=>{
return weather.city.id!==action.payload
}));
return [...state].filter((weather)=>{
return weather.city.id!==action.payload
});
default:
return state;
};
}
Before using the localStorage for persisting the application state, my code was working fine. But now it is showing me an error. I am facing a problem regarding const createStoreWithMiddleware =
applyMiddleware(ReduxPromise)(createStore);
how to use store using this middleware and how to pass in <Provider> tag's store property?
I would suggest you to use redux-persist.
Persist and rehydrate a redux store
Using this middleware all the data you have in the Redux Store will be automatically persisted to the localStorage (different type of storage can be used too). Therefore, when you refresh a page, the already persisted data from the previous request will be automatically rehydrated (pushed) back to the Store.
Example, taken from documentation:
Configuration:
// configureStore.js
import { createStore } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web and AsyncStorage for react-native
import rootReducer from './reducers'
const persistConfig = {
key: 'root',
storage,
}
const persistedReducer = persistReducer(persistConfig, rootReducer)
export default () => {
let store = createStore(persistedReducer)
let persistor = persistStore(store)
return { store, persistor }
}
Usage:
import { PersistGate } from 'redux-persist/integration/react'
// ... normal setup, create store and persistor, import components etc.
const App = () => {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<RootComponent />
</PersistGate>
</Provider>
);
};
I am a novice in Javascript and Redux, and I just created my first app based on this tutorial. I have a problem that the Store absolutely doesn't react to any dispatch call. I don't know if there is an error in the connection between Redux and React or in the store configuration itself.
Could you please help me with this problem?
This is snippes from my actions file where "addTodo" action is defined.
export const ADD_TODO = 'ADD_TODO';
let todoId = 0;
export const addTodo = (text) => ({
type: ADD_TODO,
id: todoId++,
text,
});
Below is my Store configuration.
import { createStore, applyMiddleware, compose } from 'redux';
import rootReducer from '../reducers';
import DevTools from '../containers/DevTools';
const enhancer = compose(
applyMiddleware(createLogger),
DevTools.instrument()
);
export default function configureStore(initialState) {
const store = createStore(rootReducer, initialState, enhancer);
if (module.hot) {
module.hot.accept('../reducers', () => {
const nextRootReducer = require('../reducers').default;
store.replaceReducer(nextRootReducer);
});
}
return store;
}
My index file where I try to call a dispatch function with "AddTodo" action creator. Similarly, I call this function in Redux containers, but it doesn't work for both.
import React from 'react';
import { render } from 'react-dom';
import configureStore from './store/configureStore';
import { addTodo } from './actions';
const store = configureStore();
store.subscribe(() =>
console.log(store.getState())
);
store.dispatch(addTodo('test'));
The whole project is placed on Github too. I will be thankful if you help me.
you forgot to invoke createLogger, try
const enhancer = compose(
applyMiddleware(createLogger())
...
);
webpackbin test