I can't use connect, with export in App component. No error is thrown, the app starts normally... but all my links in my navbar stop to work (???). The url changes, but the main page is always displayed, like it would break the routing. Here is my code:
import { Route, Switch, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import Layout from './hoc/Layout/Layout';
import BurgerBuilder from './containers/BurgerBuilder/BurgerBuilder';
import Checkout from './containers/Checkout/Checkout';
import Orders from './containers/Orders/Orders';
import Auth from './containers/Auth/Auth';
import * as actions from './store/actions'
class App extends Component {
render () {
return (
<div>
<Layout>
<Switch>
<Route path="/checkout" component={Checkout} />
<Route path="/orders" component={Orders} />
<Route path="/auth" component={Auth} />
<Route path="/" exact component={BurgerBuilder} />
</Switch>
</Layout>
</div>
);
}
}
const mapDispatchToProps = dispatch => {
return {
anything: ()=>dispatch(actions.logout())
}
};
export default connect(null, mapDispatchToProps)(App);
//export default App;
If I comment the 'connect' part, like this:
//export default connect(null, mapDispatchToProps)(App);
export default App;
everything runs ok and all my links are working fine. Why can't I use 'connect' in my App component? I know I'm not dispatching any actions through props, but it should work nontheless, as far as I'm concerned.
Below is my index.js file, which uses th App component:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import burgerBuilderReducer from './store/reducers/burgerBuilder';
import orderReducer from './store/reducers/order';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const rootReducer = combineReducers({
burgerBuilder: burgerBuilderReducer,
order: orderReducer
});
const store = createStore(rootReducer, composeEnhancers(
applyMiddleware(thunk)
));
const app = (
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
ReactDOM.render( app, document.getElementById( 'root' ) );
registerServiceWorker();
I think the problem is your mapDispatchToProps:
import {bindActionCreators} from 'redux'
...
const mapDispatchToProps = dispatch => (bindActionCreators({
actionName: () => ({type:'SOME_ACTION', payload: 'SOME_PAYLOAD'}),
doLogout: () => actions.logout(),
}, dispatch))
EDIT: Do this changes to your App.js
<BrowserRouter>
<Switch>
<Route path="/checkout" component={Checkout} />
<Route path="/orders" component={Orders} />
<Route path="/auth" component={Auth} />
<Route path="/" exact component={BurgerBuilder} />
</Switch>
</BrowserRouter>
I think I got it. The solution was to wrap both my App and Layout components (layout holds my navigation items) with "withRouter":
export default withRouter(connect(null, mapDispatchToProps)(App));
export default withRouter(connect(mapStateToProps)(Layout));
Related
In my react application, I created store.js and rootreducer.js for it. Before creating the store.js and rootreducer.js file, my react application was working properly but after adding it, I'm actually not getting any error but my output on the local host is blank now. For including the store and reducer in my application I have imported the provider and store to my app.js file. If I remove them, my react application works properly but with these imports, I get a blank screen in my localhost. Below given is my store.js file
import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './Reducer/rootReducer';
const initialState = {}
const middleWare = [thunk]
let store;
if (window.navigator.userAgent.includes("Chrome")) {
store = createStore(rootReducer,
initialState,
compose(applyMiddleware(...middleWare),
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
))
} else {
store = createStore(rootReducer,
initialState,
compose(applyMiddleware(...middleWare)))
}
export default store;
And this is my app.js file
import React from 'react';
import './App.css';
import Nav from './Component/Common/Nav';
import 'bootstrap/dist/css/bootstrap.css';
import Welcome from './Component/Welcome';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Dashboard from './Component/Dashboard/Dashboard';
import CreateMonthWallet from './Component/Dashboard/DashboardOperations/CreateMonthWallet';
import NotFound from './Component/Common/NotFound';
import { Provider } from 'react-redux';
import store from './Store';
//import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
function App() {
return (
<Provider store={store}>
<Router>
<div>
<Nav />
<Routes>
<Route path="/" element={<Welcome />} exact />
<Route path="/Dashboard" element={<Dashboard />} exact />
<Route path="/CreateMonthWallet" element={<CreateMonthWallet />} exact />
<Route path="*" element={<NotFound />} exact />
</Routes>
</div>
</Router>
</Provider>
);
}
export default App;
And this is my rootreducer.js file
import {combineReducers} from 'redux'
export default combineReducers({
});
you can add your store like this in app.js
your code
import store from './Store';
add this
import {store} from './Store';
hope this will help you!
Is it possible to use more reducer in app, I have created several reducer files and I want to share in provider. Is it possible? I tried not many things but without success, like for example: combineReducers.
import { BrowserRouter, Routes, Route} from 'react-router-dom';
import { createStore, combineReducers} from "redux";
//import reducer from "../src/reducer/TestReducer";
import reducerAuthentification from "../src/reducer/ReducerAuthentification"
import TestReducer from "../src/reducer/TestReducer"
import './assets/style/app/App.css';
import './assets/style/app/App.scss';
import React from 'react';
import Accueil from './view/accueil/Accueil';
import Feuillete from './view/patisserie/Feuilletes';
import Footer from './view/footer/Footer';
import Reservation from './view/reservation/Reservation';
import { Provider } from 'react-redux';
import Compte from './view/client/compte/Compte';
const store = createStore(reducerAuthentification);
const store1 = createStore(TestReducer)
// const appReducers = createStore({
// reducerAuthentification: "",
// TestReducer: ""
// })
function App() {
return (
<Provider store={{store}}>
<div className="App">
<BrowserRouter>
{/* <Navbar/> */}
<header className="App-header">
<Navigation/>
</header>
<Routes>
<Route path={"/"} element={<Accueil />}/>
<Route path={"/les-patisseries/les-feuilletes"} element={<Feuillete />}/>
<Route path={"/reservation"} element={<Reservation />}/>
<Route path={"/compte"} element={<Compte />} />
</Routes>
<Footer />
</BrowserRouter>
</div>
</Provider>
);
}
export default App;
Best practice is to combine all reducer in separate file.
For example:
rootReducer.js:
const rootReducer = combineReducers({
reducer1: reducerOne,
reducer2: reducerTwo,
})
export default rootReducer
store.js:
import rootReducer from './rootReducer'
const store = createStore(rootReducer)
Redux createStore is depreceated method, it works but you should use configureStore for creating store.
See: https://redux-toolkit.js.org/introduction/getting-started
You can use combineReducers as shown in their documentation.
https://redux.js.org/api/combinereducers
I have encountered a problem with th fact that reactDOM.render doesnt render the app despite yarn run compiling sucessfully.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {Provider} from 'react-redux';
import {PersistGate} from 'redux-persist/integration/react';
import {store ,persistor} from './redux/store.js'
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
Redux configuration in store.js
import { createStore, applyMiddleware } from 'redux';
import logger from 'redux-logger';
import {persistStore} from 'redux-persist';
import createSagaMiddleware from 'redux-saga';
import { fetchGalleryStart } from './gallery/gallery.saga';
import {rootReducer} from './root.reducer.js';
const sagaMiddleware= createSagaMiddleware();
const middlewares = [sagaMiddleware];
if (process.env.NODE_ENV==='development') {
middlewares.push(logger)
}
export const store = createStore(rootReducer, applyMiddleware(...middlewares));
export const persistor = persistStore(store);
sagaMiddleware.run(fetchGalleryStart); //inside run we pass each individual saga
const exportedObject = {
store,
persistor,
};
export default exportedObject;
The app.js
import React from 'react';
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Header from './components/header/header.component.jsx';
import Footer from './components/footer/footer.component.jsx';
import HomePage from './pages/homepage/homepage.component.jsx';
import Contact from './pages/contact/contact.component.jsx';
import About from './pages/about/about.component.jsx';
class App extends React.Component {
render () {
return (
<div className="App">
<BrowserRouter>
<Header />
<div className="wrapper">
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/contact" component={Contact} />
<Route path="/about" component={About} />
<Route path="*">error</Route>
</Switch>
</div>
<Footer/>
</BrowserRouter>
</div>
);
}
};
export default App
When I open the app in the browser, the app is not rendered on the root, page stays blank.
Could you please help me where to look? I am pretty lost how to approach this since i receive no error.
Thank you for your time
Wrap your render()... method with a class component like this:
class App extends React.Component {
render() {
return ();
}
}
export default App;
To declare App correct.
Or get rid of render() method and do a function:
funciton App() => {
return (<div></div>);
}
export default App;
Hope I could help you and have fun!
I have index.js file which contains:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App'
import * as serviceWorker from './serviceWorker';
import {combineReducers,createStore,compose,applyMiddleware} from 'redux'
import {Provider} from 'react-redux'
import thunk from 'redux-thunk'
import { HashRouter } from 'react-router-dom';
import playerReducer from './store/Player/PlayerReducers'
import cardReducer from './store/Cards/cardsReducer'
import playersReducer from './store/Players/PlayersReducer'
import stylesReducer from './store/Styles/StylesReducer'
import gameReducer from './store/Game/gameReducer'
const rootReducer = combineReducers({
player: playerReducer,
cards:cardReducer,
players:playersReducer,
styles:stylesReducer,
game:gameReducer
})
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunk)))
ReactDOM.render(
<Provider store={store}>
<HashRouter >
<App />
</HashRouter>
</Provider>
, document.getElementById('root'));
serviceWorker.unregister();
export default store
and I have App.js file which contains:
import React, { PureComponent, Suspense } from 'react'
import {connect} from 'react-redux'
import './App.css'
import SignUp from './Register/SignUp'
import SignIn from './Register/SignIn'
import * as stylesActions from './store/Styles/StylesActions'
import Entrance from './components/Entrance/Entrance'
import Profile from './components/Profile/Profile'
import NotFound from './UI/NotFound/NotFound'
import Fallback from './UI/Fallback/Fallback'
import { Route, Switch } from 'react-router-dom'
const Lobby = React.lazy(() => import("./Lobby/Lobby"))
const Game = React.lazy(() => import('./containers/Game/Game'))
class App extends PureComponent {
render() {
return (
<div className="App"
data-test="App-component"
>
<Switch>
<Route path="/" exact render={() => (
<Suspense fallback={
<Fallback />
}>
<Entrance />
</Suspense>
)} />
<Route path="/auth/signup" exact component={SignUp}/>
<Route path="/auth/signin" exact component={SignIn}/>
<Route path="/lobby" exact render={() => (
<Suspense fallback={
<Fallback />
}>
<Lobby />
</Suspense>
)}/>
<Route path="/profile" exact component={Profile}/>
<Route path="/game" exact render={() => (
<Suspense fallback={
<Fallback />
}>
<Game />
</Suspense>
)} />
<Route component={NotFound} />
</Switch>
</div>
)
}
}
const mapDispatchToProps = (dispatch) => {
return {
onChangeMusicStatus:(arg) => dispatch(stylesActions.musicPaused(arg))
}
}
const mapStateToProps = (state) => {
return {
player: state.player,
styles:state.styles,
players:state.players
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
when I try to test it gives me this error
Could not find "store" in the context of "Connect(App)". Either wrap the root component in a or pass a custom React context provider to and the corresponding React context consumer to Connect(App) in connect options.
what version of react-redux are you using, can you post your test, if you are using a react-redux 7 you must wrap your text component with Provider:
const TestComponent = <Provider store={store}><App /></Provider>
your test code here...
also you can export only the App component (not the connected) and test it separately.
I'm trying to connect react router v4 with redux but it's not working. I'm using withRouter as described in the docs, but props aren't available in my route components. Any idea?
Here's my code:
index.js
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import { routerMiddleware } from 'react-router-redux';
import { createLogger } from 'redux-logger';
import thunk from 'redux-thunk';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
const logger = createLogger();
const middleware = [
thunk,
routerMiddleware(history)
];
if (process.env.NODE_ENV === 'development') {
middleware.push(logger);
}
// create store
const store = createStore(
reducers,
applyMiddleware(...middleware)
);
render(
<Provider store={store}>
<Router>
<App />
</Router>
</Provider>,
document.getElementById('root')
);
App.js
import React, { Component } from 'react';
import { Switch, Route, Link, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
class App extends Component {
componentDidMount() {
this.props.fetchPages(API_PAGES);
this.props.fetchPosts(API_POSTS);
}
render() {
return (
!this.props.pages.isFetching ?
<div>
<ul>
{this.props.pages.data && this.props.pages.data.map(page => (
<li key={page.id}>
<Link to={page.slug}>{page.title.rendered}</Link>
</li>
))}
</ul>
<Switch location={this.props.location}>
<Route path={routes.HOME} exact component={Home} />
<Route path={routes.ABOUT} component={About} />
<Route path={routes.CONTACT} component={Contact} />
<Route path={routes.NEWS} component={News} />
<Route component={NotFound} />
</Switch>
</div> :
<p>Loading...</p>
);
}
}
function mapStateToProps(state) {
return state;
}
export default withRouter(connect(
mapStateToProps,
{ ...actions }
)(App));
reducers/index.js
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
export default combineReducers({
pages,
posts,
routing: routerReducer
});
components/Home.js
import React from 'react';
const Home = (props) => {
console.log('home', props);
return (
<div>
This is the home page.
</div>
);
};
export default Home;
You should pass the props to home component like this to make it available there,
<Route path={routes.HOME} exact component={(props)=><Home {...props} newProps={value you want to pass}/> }/>
Since you are using react-router v4 you need to be using react-router-redux v5. See here
This uses a different npm package to react-router-redux installed with:
npm install --save react-router-redux#next
The routing reducer should then have the router key (not routing) in combineReducers.
You will then need to use ConnectedRouter and pass in your history object like so...
render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
document.getElementById('root')
);