I am trying to use [Redux] to update the state in my app. I can't get the dispatch method to work in fetchUser. Spare me, I'm a bit of a noob.
All I want to do is have fetchUser run when [useEffect]runs on the first render.
The error I'm getting is
dispatch is not a function. (In 'dispatch({type:actions_types_WEBPACK_IMPORTED_MODULE_12_["FETCH_USER"], payload: result })', 'dispatch' is undefined)
Its the last useEffect in the main js file.
This is the index js file:
import 'react-app-polyfill/ie9';
import 'react-app-polyfill/stable';
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import reduxThunk from 'redux-thunk';
import App from './App';
import Main from './Main';
import './helpers/initFA';
import reducers from './reducers';
const store = createStore(reducers, {}, applyMiddleware(reduxThunk));
ReactDOM.render(
<Provider store={store}>
<Main>
<App />
</Main>
</Provider>
,
document.getElementById('main')
);
Here is the Main js file:
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import AppContext from './context/Context';
import { settings } from './config';
import toggleStylesheet from './helpers/toggleStylesheet';
import { getItemFromStore, setItemToStore, themeColors } from './helpers/utils';
import { connect } from 'react-redux';
import * as actions from './actions';
import axios from 'axios';
import { FETCH_USER } from './actions/types';
const Main = props => {
const [isFluid, setIsFluid] = useState(getItemFromStore('isFluid', settings.isFluid));
const [isRTL, setIsRTL] = useState(getItemFromStore('isRTL', settings.isRTL));
const [isDark, setIsDark] = useState(getItemFromStore('isDark', settings.isDark));
const [isTopNav, setIsTopNav] = useState(getItemFromStore('isTopNav', settings.isTopNav));
const [isCombo, setIsCombo] = useState(getItemFromStore('isCombo', settings.isCombo));
const [isVertical, setIsVertical] = useState(getItemFromStore('isVertical', settings.isVertical));
const [isNavbarVerticalCollapsed, setIsNavbarVerticalCollapsed] = useState(
getItemFromStore('isNavbarVerticalCollapsed', settings.isNavbarVerticalCollapsed)
);
const [currency, setCurrency] = useState(settings.currency);
const [showBurgerMenu, setShowBurgerMenu] = useState(settings.showBurgerMenu);
const [isLoaded, setIsLoaded] = useState(false);
const [isOpenSidePanel, setIsOpenSidePanel] = useState(false);
const [navbarCollapsed, setNavbarCollapsed] = useState(false);
const [navbarStyle, setNavbarStyle] = useState(getItemFromStore('navbarStyle', settings.navbarStyle));
const toggleModal = () => setIsOpenSidePanel(prevIsOpenSidePanel => !prevIsOpenSidePanel);
const value = {
isRTL,
isDark,
isCombo,
isFluid,
setIsRTL,
isTopNav,
currency,
setIsDark,
setIsCombo,
setIsFluid,
isVertical,
toggleModal,
setIsTopNav,
navbarStyle,
setCurrency,
setIsVertical,
showBurgerMenu,
setNavbarStyle,
isOpenSidePanel,
navbarCollapsed,
setShowBurgerMenu,
setIsOpenSidePanel,
setNavbarCollapsed,
isNavbarVerticalCollapsed,
setIsNavbarVerticalCollapsed
};
const setStylesheetMode = mode => {
setIsLoaded(false);
setItemToStore(mode, value[mode]);
toggleStylesheet({ isRTL, isDark }, () => setIsLoaded(true));
};
useEffect(() => {
setStylesheetMode('isFluid');
// eslint-disable-next-line
}, [isFluid]);
useEffect(() => {
setStylesheetMode('isRTL');
// eslint-disable-next-line
}, [isRTL]);
useEffect(() => {
setStylesheetMode('isDark');
// eslint-disable-next-line
}, [isDark]);
useEffect(() => {
setItemToStore('isNavbarVerticalCollapsed', isNavbarVerticalCollapsed);
// eslint-disable-next-line
}, [isNavbarVerticalCollapsed]);
useEffect(() => {
setItemToStore('isTopNav', isTopNav);
// eslint-disable-next-line
}, [isTopNav]);
useEffect(() => {
setItemToStore('isCombo', isCombo);
// eslint-disable-next-line
}, [isCombo]);
useEffect(() => {
setItemToStore('isVertical', isVertical);
// eslint-disable-next-line
}, [isVertical]);
useEffect(() => {
setItemToStore('navbarStyle', navbarStyle);
// eslint-disable-next-line
}, [navbarStyle]);
useEffect((dispatch) => {
const result = axios.get('/api/current_user')
dispatch({type: FETCH_USER, payload: result });
}, []);
if (!isLoaded) {
toggleStylesheet({ isRTL, isDark }, () => setIsLoaded(true));
return (
<div
style={{
position: 'fixed',
top: 0,
right: 0,
bottom: 0,
left: 0,
backgroundColor: isDark ? themeColors.dark : themeColors.light
}}
/>
);
}
return <AppContext.Provider value={value}>{props.children}</AppContext.Provider>;
};
Main.propTypes = { children: PropTypes.node };
export default connect(null, actions)(Main);
Here is the App js file:
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import Layout from './layouts/Layout';
import 'react-toastify/dist/ReactToastify.min.css';
import 'react-datetime/css/react-datetime.css';
import 'react-image-lightbox/style.css';
const App = () => {
return (
<Router basename={process.env.PUBLIC_URL}>
<Layout />
</Router>
);
};
export default App;
Here is the client/src/layouts/Layout js file:
import React, { useEffect } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { toast, ToastContainer } from 'react-toastify';
import { CloseButton, Fade } from '../components/common/Toast';
import DashboardLayout from './DashboardLayout';
import ErrorLayout from './ErrorLayout';
import loadable from '@loadable/component';
const AuthBasicLayout = loadable(() => import('./AuthBasicLayout'));
const Landing = loadable(() => import('../components/landing/Landing'));
const WizardLayout = loadable(() => import('../components/auth/wizard/WizardLayout'));
const AuthCardRoutes = loadable(() => import('../components/auth/card/AuthCardRoutes'));
const AuthSplitRoutes = loadable(() => import('../components/auth/split/AuthSplitRoutes'));
const Layout = () => {
useEffect(() => {
AuthBasicLayout.preload();
Landing.preload();
WizardLayout.preload();
AuthCardRoutes.preload();
AuthSplitRoutes.preload();
}, []);
return (
<Router fallback={<span />}>
<Switch>
<Route path="/" exact component={Landing} />
<Route path="/authentication/card" component={AuthCardRoutes} />
<Route path="/authentication/split" component={AuthSplitRoutes} />
<Route path="/authentication/wizard" component={WizardLayout} />
<Route path="/errors" component={ErrorLayout} />
<Route path="/authentication/basic" component={AuthBasicLayout} />
<Route path="/dashboard" component={DashboardLayout} />
</Switch>
<ToastContainer transition={Fade} closeButton={<CloseButton />} position=. {toast.POSITION.BOTTOM_LEFT} />
</Router>
);
};
export default Layout;
import { useDispatch } from 'react-redux';
const useFetching = (someFetchActionCreator) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(someFetchActionCreator());
}, [])
}
For this example, I would recommend using useDispatch() from the react-redux function library. The above answer does not consider the async, and the result will simply return a Promise to the dispatch payload.