Диспетчеризация React Redux не является функцией

#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 . Приведенный выше ответ не учитывает асинхронность, и результат просто вернет обещание полезной нагрузке отправки.