I have a state that is getting the right object from my action but It won't seem to actually append to the state. Does anyone have any experience working with reducers in React-Redux that can lend a hand? I'm not sure why I can't return the new state.
Here is the code in progress I have at the moment.
import * as types from '../constants'
const defaultState = {}
const userReducer = (state = defaultState, action) =>{
switch(action.type){
case types.USER_LOGGED_IN:
console.log("in the logged in reducer")
console.log(action.cookie)
return {
...state,
cookie: action.cookie
}
case types.USER_LOGGED_OUT:
return state
default:
return state
}
}
export default userReducer
The console.log will actually print out the correct cookie value for me. Any ideas or help would be greatly appreciated.
per Request here is the container,
import React, { Component, PropTypes } from 'react'
import { routerActions } from 'react-router-redux'
import { connect } from 'react-redux'
import GoogleLogin from '../components/GoogleLogin'
import actions from '../actions/'
import cookie from 'react-cookie'
const login = actions.userActions.login
function select(state, ownProps) {
const isAuthenticated = state.user.cookie || false
console.log(isAuthenticated)
const redirect = ownProps.location.query.redirect || '/'
return {
isAuthenticated,
redirect
}
}
class LoginContainer extends Component {
componentWillMount() {
const { isAuthenticated, replace, redirect } = this.props
if (isAuthenticated) {
replace(redirect)
}
}
componentWillReceiveProps(nextProps) {
const { isAuthenticated, replace, redirect } = nextProps
const { isAuthenticated: wasAuthenticated } = this.props
if (!wasAuthenticated && isAuthenticated) {
replace(redirect)
}
}
onClick(e){
e.preventDefault()
//console.log("in the onClick")
var status = cookie.load("MarketingStatsApp",false)
if(!(status == undefined)){
const login = actions.userActions.login
this.props.login({
cookie: status
})
}
window.location.href='auth/google'
};
render() {
return (
<div>
<h1>Login using Google</h1>
<GoogleLogin onClick={this.onClick.bind(this)}/>
</div>
)
}
}
export default connect(select, { login, replace: routerActions.replace })(LoginContainer)
Here you can see the false get printed out the first time through and then the cookie get printed out. You can even see the action but I can't click into the arrows for that action and the the other ones don't display the updated state as how I expect it to be
Thanks for the help everyone
The problem ended up being on my double verification on my router page. I needed to re-bring in the action variable for it to launch properly. Here is the code for that
import { Router, Route, browserHistory,IndexRedirect } from 'react-router'
import React from 'react';
import Layout from './components/Layout'
import Home from './containers/Home'
import Login from './containers/LoginContainer'
import Dashboard from './containers/Dashboard'
import { UserIsAuthenticated} from './util/wrapper'
import cookie from 'react-cookie'
import axios from 'axios'
import actions from './actions'
import store from './reducers';
const Authenticated = UserIsAuthenticated((props) => props.children)
function doubleCheckGUID(guid){
return axios.post("/auth/guid",{guid: guid}).then(response => {
const login = actions.userActions.login
store.dispatch(login({
cookie: cookie.load("MarketingStatsApp",false)
}))
return true;
}).catch(error => {
return false;
})
}
if(cookie.load("MarketingStatsApp",false)){
doubleCheckGUID(cookie.load("MarketingStatsApp",false))
}
const AppRouter = () =>
<Router history={browserHistory} >
<Route path="/" component={Layout}>
<IndexRedirect to="/home" />
<Route path="home" component={Home} />
<Route path="login" component={Login}/>
<Route component={Authenticated} >
<Route path="dash" component={Dashboard} />
</Route>
</Route>
</Router>
export default AppRouter
Related
I'm coding an app that requires you to login using Laravel/Sanctum as the backend (no JWT). I'm using localStorage to persist the user's login details in case the browser page is reloaded, I can then re-apply state in my useAuthHandler hook.
This works fine, but I would like to either:
a) Replace the localStorage with an Axios request to ensure I re-apply state with genuine login data from the backend (i.e. the user did not forge localStorage details) before rendering the app.
--- OR ---
b) Keep using localStorage, but send an Axios request back to the server to confirm the localStorage details were indeed valid before rendering any of the app.
With the following code, I'm having trouble making the Axios request synchronous in the getStoredAuth() function where the localStorage is fetched. I need to avoid having my app render before the request has returned. This is so I can avoid any page 'flash' while auth details are being checked.
AuthContext.js
import useAuthHandler from "../utils/custom-hooks/AuthHandler";
import { getStoredUserAuth } from "../helpers/Helpers";
export const authContext = createContext();
const { Provider } = authContext;
const AuthProvider = ({ children }) => {
const { isAuthenticated, user, setAuthStatus, setUnauthStatus } = useAuthHandler(
getStoredUserAuth()
);
return (
<Provider value={{ isAuthenticated, user, setAuthStatus, setUnauthStatus }}>
{children}
</Provider>
);
};
export default AuthProvider;
AuthHandler.js
import { useState } from "react";
import { DEFAULT_USER_AUTH } from "../Consts";
const useAuthHandler = (initialState) => {
const [isAuthenticated, setIsAuthenticated] = useState(initialState.isAuthenticated);
const [user, setUser] = useState(initialState.user);
const setAuthStatus = (userAuth) => {
window.localStorage.setItem("UserAuth", JSON.stringify(userAuth));
setIsAuthenticated(userAuth.isAuthenticated);
setUser(userAuth.user);
};
const setUnauthStatus = () => {
window.localStorage.clear();
setIsAuthenticated(DEFAULT_USER_AUTH.isAuthenticated);
setUser(DEFAULT_USER_AUTH.user);
};
return {
isAuthenticated,
user,
setAuthStatus,
setUnauthStatus,
};
};
export default useAuthHandler;
Helpers.js
import { DEFAULT_USER_AUTH } from "../utils/Consts";
/** Return user auth from local storage value */
export const getStoredUserAuth = () => {
const auth = window.localStorage.getItem("UserAuth");
if (auth) {
/**
* Axios synchronous check with server if login is still valid here
* before returning any data.
*
* If the localStorage data is invalid, or the server's session has
* expired, then redirect to /login before rendering anything.
*/
return JSON.parse(auth);
}
return DEFAULT_USER_AUTH;
};
Consts.js
export const DEFAULT_USER_AUTH = { isAuthenticated: false, user: {} };
App.js
import { IonApp, IonRouterOutlet, setupIonicReact } from '#ionic/react';
import { IonReactRouter } from '#ionic/react-router';
import { Redirect, Route, Switch } from 'react-router-dom';
import routes from './routes';
import { useState, useEffect } from 'react';
import { Content, Page } from "./components/IonComponents";
import { useSelector } from "react-redux";
import Menu from "./components/Menu/Menu";
import { PrivateRoute } from "./components/Menu/PrivateRoute";
import AuthContextProvider from "./contexts/AuthContext";
/* Core CSS required for Ionic components to work properly */
import '#ionic/react/css/core.css';
/* Stylesheets */
import './assets/scss/variables.scss';
import "bootstrap/dist/css/bootstrap.min.css";
import "./assets/scss/propeller-styles.scss";
setupIonicReact();
const App = () => {
const [displayMenuExpanded, setDisplayMenuExpanded] = useState(false);
const menuExpanded = useSelector((state) => state.menuExpanded.value);
useEffect(() => {
setDisplayMenuExpanded(menuExpanded);
}, [menuExpanded]);
return (
<IonApp>
<IonReactRouter basename={process.env.PUBLIC_URL}>
<AuthContextProvider>
<Menu expanded={displayMenuExpanded} />
<IonRouterOutlet
className={displayMenuExpanded ? "router-narrow" : "router-expanded"}
>
<Switch>
<>
<Page>
<Content
className={
displayMenuExpanded ? "content-narrow" : "content-expanded"
}
>
<div id="content-wrapper">
<Route exact path="/">
<Redirect to="/utilities" />
</Route>
{routes.map((route, key) => (
<PrivateRoute
key={key}
path={route.pathname}
exact
component={route.component}
/>
))}
</div>
</Content>
</Page>
</>
</Switch>
</IonRouterOutlet>
</AuthContextProvider>
</IonReactRouter>
</IonApp >
);
};
export default App;
PrivateRoute.js
import { useContext } from 'react'
import { Route, Redirect } from 'react-router-dom';
import { authContext } from "../../contexts/AuthContext";
export { PrivateRoute };
function PrivateRoute({ component: Component, ...rest }) {
const authCtx = useContext(authContext);
if (!Component) return null;
return (
<Route {...rest} render={props => {
if (!authCtx.isAuthenticated && props.location.pathname !== "/login") {
// Not logged-in so redirect to login page with the return url
return <Redirect to={{ pathname: '/login', state: { from: props.location } }} />
}
// Authorised so return component
return <Component {...props} />
}} />
);
}
The above PrivateRoute component is how I redirect the user if they're not authenticated.
Thank you for your help.
When a user is authenticated, I can refresh the page and access all the routes through the website or by entering/refreshing the URL. However, when the user is unauthenticated, although the routing through the website works well, refreshing the URL even on plain route pages (non-private) redirects me to index (main page).
I have used this as the template of my react app and this for adding authentication to my react app. I have tried these two guides seperately and both work well but somehow in my react app their combination leads to the issue I described above.
Below is the code for my app routes:
import React, { Component, lazy, Suspense} from 'react';
import { Switch, Route, Redirect } from 'react-router-dom';
import Spinner from '../app/shared/Spinner';
const MainIndex = lazy(() => import( "./mainpage/Index"));
const TermsIndex = lazy(() => import( "./mainpage/Terms"));
const Dashboardmain = lazy(() => import( "./dashboard/Dashboardmain"));
const Login = lazy(() => import( "./user-pages/Login"));
const Register = lazy(() => import( "./user-pages/Register"));
class AppRoutes extends Component {
render () {
return (
<Suspense fallback={<Spinner/>}>
<Switch>
<Route exact path="/login" component={ Login } />
<Route exact path="/index" component={ MainIndex } />
<Route exact path="/terms" component={ TermsIndex } />
<PrivateRoute exact path="/internal/dashboard" component={ Dashboardmain } />
<Route exact path="/register" component={ Register } />
</Switch>
</Suspense>
);
}
}
export default AppRoutes;
My app pages look like this - the FullPageLayout is to check if header, footer or sidebar should be added for the page or not:
import React, { Component } from 'react';
import AppRoutes from './AppRoutes';
import Navbar from './shared/Navbar';
import Sidebar from './shared/Sidebar';
import Footer from './shared/Footer';
import { withRouter } from 'react-router-dom';
class AppPages extends Component {
state = {}
componentDidMount() {
this.onRouteChanged();
}
render () {
let navbarComponent = !this.state.isFullPageLayout ? <Navbar/> : '';
let sidebarComponent = !this.state.isFullPageLayout ? <Sidebar/> : '';
let footerComponent = !this.state.isFullPageLayout ? <Footer/> : '';
return (
<div className="container-scroller">
{ sidebarComponent }
<div className="container-fluid page-body-wrapper">
{ navbarComponent }
<div className="main-panel">
<div className="content-wrapper">
<AppRoutes/>
</div>
{ footerComponent }
</div>
</div>
</div>
);
}
componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
this.onRouteChanged();
}
}
onRouteChanged() {
const containment = [];
const fullPageLayoutRoutes = ['/login', '/register',
'/index', '/terms'];
const body = document.querySelector('body');
body.classList.remove('rtl')
for (var i = 0; i < fullPageLayoutRoutes.length; i++) {
containment[containment.length] = this.props.location.pathname.toLowerCase().includes(fullPageLayoutRoutes[i])
}
if (containment.includes(true)) {
this.setState({isFullPageLayout: true})
document.querySelector('.page-body-wrapper').classList.add('full-page-wrapper');
} else {
this.setState({isFullPageLayout: false})
document.querySelector('.page-body-wrapper').classList.remove('full-page-wrapper');
}
}
}
export default withRouter(AppPages);
And my app is as follows:
import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import './App.scss';
import { Provider } from "react-redux";
import jwt_decode from "jwt-decode";
import setAuthToken from "../utils/setAuthToken";
import { setCurrentUser, logoutUser } from "../actions/authActions";
import store from "../store";
import AppPages from './AppPages';
// Check for token to keep user logged in
if (localStorage.jwtToken) {
// Set auth token header auth
const token = localStorage.jwtToken;
setAuthToken(token);
// Decode token and get user info and exp
const decoded = jwt_decode(token);
// Set user and isAuthenticated
store.dispatch(setCurrentUser(decoded));
// Check for expired token
const currentTime = Date.now() / 1000; // to get in milliseconds
if (decoded.exp < currentTime) {
// Logout user
store.dispatch(logoutUser());
// Redirect to login
window.location.href = "/login";
}
}
class App extends Component {
render () {
return (
<Provider store={store}>
<BrowserRouter>
<AppPages/>
</BrowserRouter>
</Provider>
);
}
}
export default App;
I tried debugging the issue by changing/simplifying things in the router or app part but I don't think the problem is here. I think the problem is somewhere within the reducers or actions.
My store is defined as follows:
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(...middleware),
(window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__()) ||
compose
)
);
export default store;
My authReducer is defined as:
import { SET_CURRENT_USER, USER_LOADING } from "../actions/types";
const isEmpty = require("is-empty");
const initialState = {
isAuthenticated: false,
user: {},
loading: false
};
export default function(state = initialState, action) {
switch (action.type) {
case SET_CURRENT_USER:
return {
...state,
isAuthenticated: !isEmpty(action.payload),
user: action.payload
};
case USER_LOADING:
return {
...state,
loading: true
};
default:
return state;
}
}
My authAction is defined as:
import axios from "axios";
import setAuthToken from "../utils/setAuthToken";
import jwt_decode from "jwt-decode";
import { GET_ERRORS, SET_CURRENT_USER, USER_LOADING } from "./types";
// Register User
export const registerUser = (userData, history) => dispatch => {
axios
.post("/api/users/register", userData)
.then(res => history.push("/login")) // re-direct to login on successful register
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Login - get user token
export const loginUser = userData => dispatch => {
axios
.post("/api/users/login", userData)
.then(res => {
// Save to localStorage
// Set token to localStorage
const { token } = res.data;
localStorage.setItem("jwtToken", token);
// Set token to Auth header
setAuthToken(token);
// Decode token to get user data
const decoded = jwt_decode(token);
// Set current user
dispatch(setCurrentUser(decoded));
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Set logged in user
export const setCurrentUser = decoded => {
return {
type: SET_CURRENT_USER,
payload: decoded
};
};
// User loading
export const setUserLoading = () => {
return {
type: USER_LOADING
};
};
// Log user out
export const logoutUser = () => dispatch => {
// Remove token from local storage
localStorage.removeItem("jwtToken");
// Remove auth header for future requests
setAuthToken(false);
// Set current user to empty object {} which will set isAuthenticated to false
dispatch(setCurrentUser({}));
};
It's something to do with the order of execution. The redux state gets erased when you refresh so you need the store.dispatch(setCurrentUser(decoded)) to get called before the PrivateRoute tries to render. It's not obvious to me precisely where it's going wrong because the if (localStorage.jwtToken) { block is not async, though the dispatch might be?
I would recommend setting the initialState in authReducer to isAuthenticated: null and update to either true or false once you've examined the token. Right now your PrivateRoute only knows two states: authenticated and unauthenticated. We need it to understand a third which is "I don't know yet". In your PrivateRoute you would render nothing or a loading spinner while isAutheticated is null. Don't render the Redirect until you have a definite false.
So after some debugging, I realised that my problem is coming from AppPages and the line with { navbarComponent }. This navbar is used with the PrivateRoute and requires the user to be defined. When the user is unauthenticated, although this will not technically render for plain routes, it is still processed and inside this navbar is a condition that if the user is undefined, will return to the index page.
I want to login user automatically if refresh_token exists in localStorage but my issue here is, i am not able to change state to authenticated initially when app start. I tried with componentWillMount but i am getting old state 1st time then i get updated state. <PrivateRoute> here getting called 2-3 time, don't know where i am making mistake.
Expected Flow
autoLogin
PrivateRoute with new state
App.js
import React, { Component } from 'react'
import WrappedLoginForm from './containers/Login'
import ChatApp from './containers/Chat'
import { connect } from 'react-redux'
import { checkAuthentication } from './store/actions/auth'
import PrivateRoute from './route'
import {
BrowserRouter as Router,
Route
} from "react-router-dom";
class App extends Component {
componentWillMount() {
this.props.autoLogin()
}
render() {
return (
<Router>
<Route path='/login' component={WrappedLoginForm} />
<PrivateRoute path="/" component={ChatApp} authed={this.props.isAuthenticated} />
</Router>
)
}
}
const mapStateToProps = state => {
return {
isAuthenticated: state.isAuthenticated,
loading: state.loading
}
}
const mapDispatchToProps = dispatch => {
return {
autoLogin: () => {
dispatch(checkAuthentication())
}
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(App)
route.js
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
const PrivateRoute = ({ component: Component, authed, ...rest }) => {
console.log('aaa')
return (<Route
render={props => (
authed
? <Component />
: <Redirect to="/login" />
)}
/>)
};
export default PrivateRoute;
action.js
export const checkAuthentication = () => {
return dispatch => {
dispatch(authStart())
let refresh_token = localStorage.getItem('refresh_token')
axiosInstance.post('/api/token/refresh/', {
refresh: refresh_token
}).then(res => {
if (res.status === 200) {
localStorage.setItem("access_token", res.data.access)
dispatch(loginSuccess())
}
}).catch(error => {
console.log("balle")
dispatch(loginFailed(error))
})
}
}
first thing make sure that in your store the isAuthenticated property is false by default.
For PrivateRoute use :
{this.props.isAuthenticated
? <PrivateRoute path="/" component={ChatApp} />
: null
}
instead of <PrivateRoute path="/" component={ChatApp} authed={this.props.isAuthenticated} />
I have a component I am using for authentication, if a user is not authenticated I want to push them to the login page.
A basic example of the setup is...
Auth Component
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { auth } from '../../firebase';
import { replace } from 'react-router-redux';
export default (WrappedComponent, {}) => {
class Authentication extends Component {
componentWillMount() {
auth.onAuthStateChanged(user => {
if (user) {
// User is signed in.
console.log('USER IS SIGNED IN');
} else {
// No user is signed in.
console.log('USER IS NOT SIGNED IN');
this.props.dispatch(replace('login'));
}
});
}
render() {
return <WrappedComponent>{this.props.children}</WrappedComponent>;
}
}
return connect(
null,
null
)(Authentication);
};
Routes
import React from 'react';
import Loadable from 'react-loadable';
import { Router, Route, IndexRoute } from 'react-router';
import AuthenticationComponent from './containers/Authentication';
import App from './components/App';
const AsyncRoute = loader =>
Loadable({
loader,
loading: () => <h3>Loading...</h3>,
delay: 300,
});
const LandingPage = AsyncRoute(() =>
import(/* webpackPrefetch: true, webpackChunkName: "landingPage" */ './containers/LandingPage')
);
const Login = AsyncRoute(() =>
import(/* webpackPrefetch: true, webpackChunkName: "login" */ './containers/Login')
);
const NotYetImplemented = () => <h6>Not Yet Implemented...</h6>;
export default ({ history }) => (
<Router history={history}>
<Route path="/" component={AuthenticationComponent(App, {})}>
<IndexRoute component={LandingPage} />
</Route>
<Route path="/login" component={Login} />
</Router>
);
Currently, when Firebase reports the user is not authenticated, the route is updated and shows as http://localhost:3001/login however the LandingPage component is rendered.
If I refresh the page on /login I do then get the correct component.
I have swapped out replace for push but had the same result.
like #Boo said you have to use exact or you can use switch and Route instead like this
import { Switch, Route} from 'react-router-dom'
<Switch>
<Route path='/' component={ HomePage } exact />
<Route path='/login' component={ LogIn } exact />
</Switch>
and using
Redirect
you can do something like this (the code below) instead of dispatching action in redux and this will work for sure
import { Redirect } from 'react-router'
export default (WrappedComponent, {}) => {
class Authentication extends Component {
state = { redirect : false }
componentWillMount() {
auth.onAuthStateChanged(user => {
if (user) {
// User is signed in.
console.log('USER IS SIGNED IN');
} else {
// No user is signed in.
console.log('USER IS NOT SIGNED IN');
//this.props.dispatch(replace('login'));
this.setState({redirect : true})
}
});
}
render() {
const {redirect } = this.state
if(!redirect){
return <WrappedComponent>{this.props.children}</WrappedComponent>;
} else {
return <Redirect to='where ever you want' />
}
}
Not really sure how to move forward on this one. I have a (fairly) simple setup with react-router, almost everything works as expected - I get requests and responses between the app and my api - except I have a function I expect to run from my app's componentDidMount lifecycle function, but it's somehow not getting hit...
Here's a pretty minimal version of my code:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Switch } from 'react-router';
import { connect } from 'react-redux';
import { authenticate, unauthenticate } from './actions/session';
import RouteAuthenticated from './RouteAuthenticated'; // Route if authenticated
import RedirectAuthenticated from './RedirectAuthenticated'; // Redirect to login if not authenticated
import Home from './Home';
import Login from './Login';
import Signup from './Signup';
class App extends Component {
componentDidMount() {
const token = localStorage.getItem('token'); // eslint-disable-line no-undef
console.info(token); // <==== Shows a token, great!
console.info(this.props.authenticate.toString()); // Output below
if (token) {
console.info(`We have a token`); // <=== I get to here
this.props.authenticate(); // <=== Never gets run...????
} else {
this.props.unauthenticate();
}
}
render() {
const { isAuthenticated, willAuthenticate } = this.props;
const authProps = { isAuthenticated, willAuthenticate };
return (
<div className="App">
<Header />
<Switch>
<RouteAuthenticated exact path="/" component={Home} {...authProps} />
<RedirectAuthenticated exact path="/login" component={Login} {...authProps} />
<RedirectAuthenticated exact path="/signup" component={Signup} {...authProps} />
</Switch>
</div>
);
}
}
App.propTypes = {
authenticate: PropTypes.func.isRequired,
unauthenticate: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool.isRequired,
willAuthenticate: PropTypes.bool.isRequired
};
const mapStateToProps = (state) => ({
isAuthenticated: state.isAuthenticated,
willAuthenticate: state.willAuthenticate
});
const mapDispatchToProps = () => ({
authenticate,
unauthenticate
});
export default connect(mapStateToProps, mapDispatchToProps)(App);
And since this seemed super weird, I decided to go ahead and just make sure that there actually was a function to run. I put in the console.info(this.props.authenticate.toString()); line above, and here's what I get, which looks fine except that it never actually runs:
function authenticate() {
return function (dispatch) {
console.info("auth function");
dispatch({
type: 'AUTHENTICATION_REQUEST'
});
try {
console.info("AUTHing");
setCurrentUser(dispatch, _api2.default.get('is-auth'));
} catch (e) {
console.info("AUTH ERROR");
localStorage.removeItem('token'); // eslint-disable-line no-undef
window.location = '/login'; // eslint-disable-line no-undef
}
};
}
And here is the original function:
export const authenticate = () => (dispatch) => {
console.info("auth function"); // <=== never called?
dispatch({
type: 'AUTHENTICATION_REQUEST'
});
try {
console.info("AUTHing");
setCurrentUser(dispatch, api.get('is-auth'));
} catch (e) {
console.info("AUTH ERROR");
localStorage.removeItem('token');
window.location = '/login';
}
};
And the store:
import { createStore, applyMiddleware } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk';
import history from './history';
import reducers from './reducers';
const middleWare = [thunk, routerMiddleware(history)];
const createStoreWithMiddleware = applyMiddleware(...middleWare)(createStore);
const store = createStoreWithMiddleware(reducers);
export default store;
Any ideas what I can try from here?