Here is my code:
store.js
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__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()) ||
compose
)
);
App.js
import React, { Component } from 'react';
import './sass/main.scss';
import { BrowserRouter as Router, Route } from "react-router-dom";
import Landing from './components/pages/Landing';
import { Provider } from "react-redux";
import store from "../src/store";
import Register from "./components/auth/Register";
import Login from "./components/auth/Login";
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Route exact path='/' component={Landing}/>
<Route exact path="/login" component={Login}/>
<Route exact path="/register" component={Register}/>
</div>
</Router>
</Provider>
);
}
}
export default App;
I can't find where the problem is. I tried to debug it, but can't found what really make it those error. error: Uncaught TypeError: store.getState is not a function.
./src/App.js
Attempted import error: '../src/store' does not contain a default export (imported as 'store').
The first thing tried is adding a export default createStore but that bring up other error message saying Line 10: 'store' is assigned a value but never used and TypeError: store.getState is not a function
In your App.js you are trying to import store from "../src/store";. So system will try to import something from ../src/store.js but you never export any variable in that file.
You can update store.js to add export statement
const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(...middleware),
(window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()) ||
compose
)
);
export default store;
Related
I am trying to implement react-admin in my project however upon render I get this message
Uncaught Error: Missing history prop. When integrating react-admin inside an existing redux Provider, you must provide the same 'history' prop to the <Admin> as the one used to bootstrap your routerMiddleware. React-admin uses this history for its own ConnectedRouter.
There is very little to be found about this issue and I'm not entirely sure how to go about setting the history. I've tried importing createHistory from 'history/createHashHistory' but then I get this error
Uncaught Could not find router reducer in state tree, it must be mounted under "router"
Is there a way to get this rendering properly? And if so, what would be the proper way to go about configuring the Admin Component's history?
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { createStore, compose, applyMiddleware} from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import { BrowserRouter as Router } from 'react-router-dom';
import { reducer } from './redux/reducer';
import * as serviceWorker from './serviceWorker';
const store = createStore(reducer, compose(
applyMiddleware(thunk),
window.navigator.userAgent.includes('Chrome') ?
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() : compose,
),
);
ReactDOM.render(
<React.StrictMode>
<Router>
<Provider store={store}>
<App />
</Provider>
</Router>
</React.StrictMode>,
document.getElementById('root')
);
AdminPage.js
import { Admin, Resource } from 'react-admin';
import jsonServerProvider from 'ra-data-json-server';
const dataProvider = jsonServerProvider('http://localhost:3000');
const AdminPage = () => {
return (
<Admin dataProvider={dataProvider}>
<Resource name="services" />
</Admin>
)
}
export default AdminPage;
App.js
import React from 'react';
import './App.css';
import AdminPage from './components/AdminPage';
import { Switch, Route } from 'react-router-dom';
const App = () => {
return (
<div className="app">
<Switch>
<Route exact path='/manage' component={ AdminPage } />
</Switch>
</div>
);
}
export default App;
The proper way to write a reducer in this case is documented at https://marmelab.com/react-admin/CustomApp.html#using-an-existing-redux-provider.
But from what I see, you don't need one. You just added the thunk middleware, which is useless in react-admin as it already handles sagas.
I am seeing duplicate renders when I click a Link or use the back button. I can go to any page and do a real browser refresh and everything will work properly. My logger shows ##router/LOCATION_CHANGE twice and this is causing lots of warning and exceptions around duplication instances of things. This does not appear to be an issue of hashHistory vs browserHistory. As people have pointed out on github issues. I am on "react-router-redux": "4.0.7". Setting adjustUrlOnReplay to false doesn't appear to do anything. As always, really appreciate any help! Below are my configureStore and Routes js files. Can anyone help me find the problem here? Thanks! Phillip
configureStore.js
import { createStore, applyMiddleware, combineReducers, compose } from 'redux'
import thunk from 'redux-thunk'
import logger from 'redux-logger'
import rootReducer from '../reducers'
import createSagaMiddleware from 'redux-saga'
import rootSaga from '../sagas/sagas'
import promiseMiddleware from 'redux-promise-middleware'
import { syncHistoryWithStore} from 'react-router-redux'
import { browserHistory } from 'react-router'
import { apiMiddleware } from 'redux-api-middleware';
const sagaMiddleware = createSagaMiddleware()
const initialState = {
};
const enhancers = compose(
window.devToolsExtension ? window.devToolsExtension() : f => f
);
const store = createStore(rootReducer, initialState, compose(
applyMiddleware(apiMiddleware, thunk, logger(), sagaMiddleware),
typeof window === 'object' && typeof window.devToolsExtension !== 'undefined' ? window.devToolsExtension() : f => f
));
export const history = syncHistoryWithStore(browserHistory, store);
sagaMiddleware.run(rootSaga);
export default store;
routes.js
import App from './App'
import '...a bunch of different components'
import { Provider } from 'react-redux'
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
import store, { history } from './store/configureStore.js'
const router = (
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={TeamsContainer}/>
<Route path="teams" component={TeamsContainer} />
<Route path="teams/:teamId" component={TeamContainer} />
<Route path="teams/:teamId/add_member" component={AddMemberContainer} />
<Route path="teams/:teamId/team_members/:teamMemberId" component={TeamMemberContainer} />
</Route>
</Router>
</Provider>
)
if ( $('#app').length ) {
ReactDOM.render(router, document.getElementById('app'));
}
https://github.com/ReactTraining/history/issues/427
Updating to react-router v4 solve this.
Here is my code:
store.js
import {createStore, applyMiddleware, compose} from 'redux';
import {fromJS} from 'immutable';
import {routerMiddleware} from 'react-router-redux';
import createSagaMiddleware from 'redux-saga';
import createReducer from './reducers';
const sagaMiddleware = createSagaMiddleware();
export default function configureStore(initialState = {}, history) {
// Create the store with two middlewares
// 1. sagaMiddleware: Makes redux-sagas work
// 2. routerMiddleware: Syncs the location/URL path to the state
const middlewares = [sagaMiddleware, routerMiddleware(history)];
const enhancers = [applyMiddleware(...middlewares)];
const store = createStore(createReducer, fromJS(initialState), enhancers);
// Extensions
store.runSaga = sagaMiddleware.run;
store.asyncReducers = {}; // Async reducer registry
return store;
}
Routes.js
import React from 'react';
import {Route, Router, IndexRoute, browserHistory} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';
import store from './store';
import Welcome from './containers/Welcome';
const history = syncHistoryWithStore(browserHistory, store);
const routes = (
<Router history={history}>
<Route path="/">
<IndexRoute component={Welcome} />
</Route>
</Router>
);
export default routes;
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {browserHistory} from 'react-router';
import { Providers } from 'react-redux';
import configureStore from './store';
import routes from './routes';
const initialState = {};
const store = configureStore(initialState, browserHistory);
ReactDOM.render(
<Provider store={store}>
{routes}
</Provider>, document.getElementById('main-content')
);
I can't find where the culprit is. I tried to debug it, but can't found what really make it those error. error: Uncaught TypeError: store.getState is not a function
Any solution?
This is a typo that generated the error: TypeError: store.getState is not a function
Wrong
const store = createStore(()=>[], {}, applyMiddleware);
Correct
const store = createStore(()=>[], {}, applyMiddleware());
Notice the added parenthesis () on applyMiddleware.
in my case i got this error because my store was as shown below which is a function:
const store = preloadedState => {
let initialState={}
//some code to modify intialState
return createStore(reducer, initialState)
}
but in index.js i was passing store as a function and not the value it was returning.
wrong
<Provider store={store}>
<MyApp />
</Provider>
correct
<Provider store={store()}>
<MyApp />
</Provider>
Notice that in your Routes.js the store is not being initialized properly. You should add these lines:
const initialState = {};
const store = configureStore(initialState, browserHistory);
as in your index.js file.
I was doing this (a dynamic require) ..
const store = require('../store/app')
state = store.getState()
but for some reason when using require instead of import you have to do this ..
const store = require('../store/app')
state = store.default.getState()
Not sure if this will help but you named your import { Providers } instead of { Provider } from react-redux library.
In index.js we have to provide store() method as props value instead of store.
<Provider store={store()}>
{routes}
</Provider>
Updated index.js file.
import React from 'react';
import ReactDOM from 'react-dom';
import {browserHistory} from 'react-router';
import { Providers } from 'react-redux';
import configureStore from './store';
import routes from './routes';
const initialState = {};
const store = configureStore(initialState, browserHistory);
ReactDOM.render(
<Provider store={store()}>
{routes}
</Provider>, document.getElementById('main-content')
);
this is the solution, good luck 🤞
import { applyMiddleware, combineReducers, createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from 'redux-thunk'
const reducer = combineReducers({
products: []
})
const middleware = [thunk]
const store = createStore(
reducer,
composeWithDevTools(applyMiddleware(...middleware))
)
export default store
TypeError: store.getState is not a function -This error often occurs when you are not properly initializing middleware function. What you need to do is as below
You need to add paranthesis on applyMiddleware ( ) function and then it will behave as you are expecting it to do.
const store = createStore(()=>[], {}, applyMiddleware());
Replacing store with store() worked for me. Written below:
<Provider store={store()}>
{routes}
</Provider>
I'm managing my React application route with react-router and react-router-redux.
I setting router with following configuration:
import {Provider} from 'react-redux'
import {Router, browserHistory} from 'react-router'
import {createStore, combineReducers} from 'redux'
import {routerReducer} from 'react-router-redux';
import {syncHistoryWithStore} from 'react-router-redux'
import Reducers from './reducers'; // contains all my reducers,
const store = createStore(combineReducers(
{...Reducers, routerReducer}
));
const history = syncHistoryWithStore(browserHistory, store);
const AppRoute = (
<Provider store={store}>
<Router history={history}>
<Route path='login' components={PageLogin}/>
<Route path='system' components={PageSystem}>
<Route path="profile" component={PageProfile}/>
</Route>
</Router>
</Provider>
);
export default AppRoute;
When I try dispatch any router function:
import React from 'react';
import {Link, Route} from 'react-router';
import {connect} from 'react-redux';
import {replace, push} from 'react-router-redux';
class SystemMenu extends React.Component {
constructor(props) {
super(props);
this.logout = this.logout.bind(this);
}
logout() {
this.props.logout();
}
render() {
return (
<ul className="system-menu">
<li className={this.isActual("/system/profile")}>
<Link to="/system/profile">Profile</Link>
</li>
<li className={this.isActual("/system/unit")}>
<Link to="/system/unit">Units</Link>
</li>
<li>
<button onClick={this.logout}>Logout</button>
</li>
</ul>
)
}
}
const mapStateToProps = (state) => {
return {
router: state.router,
actualPage: state.menu.actualPage
};
};
const mapDispatchToProps = (dispatch) => {
return {
logout() {
dispatch(push('/login'));
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(SystemMenu);
When I click que Link component, pages is changing, But when I click the Logout button to debug, is executing dispatch(push('/login')); line, but nothing has happening, and no occur any error in the console.
What I worse in the configuration?
I tried console.log the logout inside the mapDispatchToProps function, and returning logout is not defined
const mapDispatchToProps = (dispatch) => {
console.log(push, logout);
return {
logout() {
dispatch(push('/login'));
}
};
};
combineReducers should take an object as the first argument, like this:
const store = createStore(
combineReducers({
...reducers,
routing: routerReducer
})
)
You're giving it an Array instead.
I suspect the reason why push doesn't work is because the router reducer is not registered properly.
I resolved this problem.
This problem is occurring because I has not using react-routerredux` middleware, so when I dispatching, maybe is not updating browser URL by state.
Following my route configuration:
import {Provider} from 'react-redux'
import {Router, browserHistory} from 'react-router'
import {createStore, combineReducers, applyMiddleware} from 'redux'
import {routerReducer} from 'react-router-redux';
import {syncHistoryWithStore, routerMiddleware} from 'react-router-redux'
import Reducers from './reducers'; // contains all my reducers,
const middleware = [routerMiddleware(browserHistory)];
const store = createStore(combineReducers(Reducers), compose(
applyMiddleware(...middleware)
));
const history = syncHistoryWithStore(browserHistory, store);
const AppRoute = (
<Provider store={store}>
<Router history={history}>
<Route path='login' components={PageLogin}/>
<Route path='system' components={PageSystem}>
<Route path="profile" component={PageProfile}/>
</Route>
</Router>
</Provider>
);
export default AppRoute;
Trying to hook up a React component to my Redux state, but I am getting the error:
Uncaught Error: Expected the reducer to be a function
Not quite sure where I am going wrong:
import React from 'react';
import { render } from 'react-dom';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from 'redux-promise';
import store, { history } from './store';
// Import components
import App from './components/App';
import Expenditure from './components/Expenditure';
import Income from './components/Income';
import Transactions from './components/Transactions';
import Single from './components/Single';
// import css
import css from './styles/style.styl';
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
const router = (
<Provider store={createStoreWithMiddleware(store)}>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={Expenditure} />
<Route path="/income" component={Income} />
<Route path="/expenditure" component={Expenditure} />
<Route path="/transactions" component={Transactions} />
<Route path="/expenditure/:id" component={Single} />
<Route path="/income/:id" component={Single} />
<Route path="/transaction/:id" component={Single} />
</Route>
</Router>
</Provider>
);
render(router, document.getElementById('root'));
My rootReducer:
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import expenditure from './expenditure';
const rootReducer = combineReducers({
expenditure,
routing: routerReducer
});
export default rootReducer;
And my actionCreators.js:
import axios from 'axios';
export const FETCH_EXPENDITURE = 'FETCH_EXPENDITURE';
export function fetchExpenditure() {
const request = axios.get('/api/expenditure');
return {
type: FETCH_EXPENDITURE,
payload: request
}
};
Then in my component, I am using connect to pull in the Redux state as props with the following below the Expenditure react class:
function mapStateToProps(state) {
console.log('state');
return {
expenditure: state.expenditure.all
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(actionCreators, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Expenditure);
Any tips would be incredible :)
are you using applyMiddleware correctly?
the docs have it passing applyMiddleware to the createStore function, not the other way around. i also dont see you using your rootReducer anywhere at all
try changing
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
to something like
// import rootReducer from '/path/to/rootReducer.js';
const createStoreWithMiddleware = createStore(
rootReducer,
[ ... ], //=> initial state
applyMiddleware(ReduxPromise)
)
then change your router input to
<Provider store={createStoreWithMiddleware}>
...
</Provider>