Search code examples
reactjsreduxreact-reduxreact-routerreact-router-dom

ReactJs: Component does not receive props from the store


I have this component:

import React, { Component } from "react";
import { connect } from "react-redux";
import { setInterestsSelectionCriteria } from "../../api/calls/data/ads/ads-configuration";

export class AdsConfiguration extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  componentDidMount() {
    console.log(
      "🚀 ~ file: AdsConfiguration.js ~ line 19 ~ AdsConfiguration ~ componentDidMount ~ this.props",
      this.props
    );
    // This throws an error
    // this.props.setInterestsSelectionCriteria is not a function
    // this.props.setInterestsSelectionCriteria([])
  }

  render() {
    return <div>test</div>;
  }
}

const mapStateToProps = (state) => ({
  ads: state.ads,
});

const mapDispatchToProps = {
  setInterestsSelectionCriteria,
};

export default connect(mapStateToProps, mapDispatchToProps)(AdsConfiguration);

This is what gets logged inside componentDidMount:

InterestsSelect.js:18 🚀 ~ file: InterestsSelect.js ~ line 19 ~ InterestsSelect ~ componentDidMount ~ this.props {}

And executing the action setInterestsSelectionCriteria throws this error:

this.props.setInterestsSelectionCriteria is not a function

For some strange reason, the component is not connected to the store.
I can't retrieve the store state.
I can't execute action.
Both of those are not passed to the component's props as you saw.

This is how the app is set-up:

store.js

import { createStore } from 'redux'; import reducer from './reducer';

// ==============================|| REDUX - MAIN STORE ||============================== //

export const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

index.js

import ReactDOM from 'react-dom';

// third party
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';

// project imports
import App from 'App';

// style + assets
import 'assets/scss/style.scss';
import { store } from 'store/store';

// ==============================|| REACT DOM RENDER  ||============================== //

ReactDOM.render(
    <Provider store={store}>
        <BrowserRouter>
            <App />
        </BrowserRouter>
    </Provider>,
    document.getElementById('root')
);

App.js

import { useDispatch, useSelector } from "react-redux";

import { ThemeProvider } from "@mui/material/styles";
import { CssBaseline, StyledEngineProvider } from "@mui/material";

// routing
import Routes from "routes";

// defaultTheme
import themes from "themes";

// project imports
import NavigationScroll from "layout/NavigationScroll";
import { apiCheckToken } from "api/calls/auth/checkToken";
import { useAxios } from "api/axiosHook";
import { useEffect } from "react";
import { actions } from "store/actions";
import cookies from "react-cookies";

// ==============================|| APP ||============================== //

const App = () => {
  const [axios, cancel] = useAxios();
  const customization = useSelector((state) => state.customization);
  const dispatch = useDispatch();
  useEffect(() => {
    try {
      if (!cookies.load("token")) throw new Error();
      (async () => await apiCheckToken({ axios }))();
      return () => cancel.cancel();
    } catch (e) {
      cookies.remove("token");
      dispatch({
        type: actions.SET_LOGGED_OUT,
      });
    }
  }, []);
  return (
    <StyledEngineProvider injectFirst>
      <ThemeProvider theme={themes(customization)}>
        <CssBaseline />
        <NavigationScroll>
          <Routes />
        </NavigationScroll>
      </ThemeProvider>
    </StyledEngineProvider>
  );
};

export default App;

Routes.js

import { useRoutes } from 'react-router-dom';

// routes
import MainRoutes from './MainRoutes';
import AuthenticationRoutes from './AuthenticationRoutes';
import config from 'config';

// ==============================|| ROUTING RENDER ||============================== //

export default function ThemeRoutes() {
    return useRoutes([MainRoutes, AuthenticationRoutes], config.basename);
}

MainRoutes

import MainLayout from "layout/MainLayout";
import { ProtectedRoute } from "./ProtectedRoute";
import { AdsConfiguration } from "views/ads-configuration/AdsConfiguration";

const MainRoutes = {
  path: "/",
  element: <ProtectedRoute Component={MainLayout} />,
  children: [
    {
      path: "/ads_configuration",
      element: <AdsConfiguration />,
    },
  ],
};

export default MainRoutes;

Solution

  • You are exporting both the connected and the unconnected version of your component and then importing the unconnected one. The connected one is your default export.

    So, do

    import AdsConfiguration from "views/ads-configuration/AdsConfiguration";