#reactjs #redux #dispatch
#reactjs #redux #отправка
Вопрос:
Я пытаюсь использовать [Redux] для обновления состояния в моем приложении. Я не могу заставить метод отправки работать в fetchUser. Избавьте меня, я немного новичок.
Все, что я хочу сделать, это запустить fetchUser при запуске [useEffect] при первом рендеринге.
Ошибка, которую я получаю, это
отправка не является функцией. (В ‘dispatch({type:actions_types_WEBPACK_IMPORTED_MODULE_12_ [«FETCH_USER»], полезная нагрузка: результат })’, ‘dispatch’ не определено)
Это последний эффект использования в основном файле js.
Это индексный js-файл:
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')
);
Вот основной файл js:
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);
Вот js-файл приложения:
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;
Вот файл client / src / layouts /Layout js:
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;
Комментарии:
1. Я
useDispatch
также рекомендую, ноconnect
будет работать, если вы используете его правильно. Вам нужно получить доступdispatch
изprops
.useEffect(() => { const result = axios.get('/api/current_user'); props.dispatch({type: FETCH_USER, payload: result }); }, []);
Или разрушение реквизита:const Main = ({dispatch, children}) => {
Ответ №1:
import { useDispatch } from 'react-redux';
const useFetching = (someFetchActionCreator) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(someFetchActionCreator());
}, [])
}
Для этого примера я бы рекомендовал использовать useDispatch() из библиотеки функций react-redux . Приведенный выше ответ не учитывает асинхронность, и результат просто вернет обещание полезной нагрузке отправки.