brocoders / redux-async-connect

It allows you to request async data, store them in redux state and connect them to your react component.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Uncaught TypeError: mapStateToProps[key] is not a function

dfcarpenter opened this issue · comments

Not sure where I am going wrong but I am trying to use this purely client side (not a universal app) and fetch data from an external api before the component/s load but I keep getting this error

Uncaught TypeError: mapStateToProps[key] is not a function

Here is my reducer index

import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';
import { reducer as reduxAsyncConnect } from 'redux-async-connect'
import { items } from './items';
import { flows } from './flows';

const rootReducer = combineReducers({
  reduxAsyncConnect,
  form: formReducer,
  items,
  flows
});

export default rootReducer;

Here is where I configure the store

export default function configureStore(initialState) {
  const logger = createLogger({
    collapsed: true,
    predicate: () =>
    process.env.NODE_ENV === `development`, 
  });

  const enhancer = compose(
      applyMiddleware(
          thunkMiddleware,
          logger
      )
  )

  const store = createStore(
       rootReducer,
       initialState,
       enhancer);

  if (module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('../reducers', () => {
      const nextRootReducer = require('../reducers').default;
      store.replaceReducer(nextRootReducer);
    });
  }

  return store;
}

here is my main file

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Router, hashHistory } from 'react-router';
import { ReduxAsyncConnect } from 'redux-async-connect'
import configureStore from './store/configureStore';
import routes from './routes';

const store = configureStore();

ReactDOM.render(
  <Provider store={store} key="provider">
    <Router render={(props) => <ReduxAsyncConnect {...props} filter={item => !item.deferred} history={hashHistory}  />} >
        {routes}
    </Router>
  </Provider>,
  document.getElementById('root')
);

Here is the component I am trying to load

import React, { Component, PropTypes } from 'react';
import { asyncConnect } from 'redux-async-connect';

@asyncConnect([{
   key: 'flows',
    promise: ({ store: { dispatch, getState } }) => {
        return dispatch(fetchCollections());
    }
}])
export class Flows extends Component {

    static propTypes = {
        flows: PropTypes.object,
    };

   .... left out rest

For the asyncConnect part I am very confused as to what exactly to include here to make sure the data is fetched. I want to check the state for my "flows" part of the global state, see if it is present and if not fetch it from the external api. Also, I am unclear when and if I need to use the @connect decorator. Anyways, any help is appreciated.

@dfcarpenter hello.
As long as you decorate your component with@asyncConnect you don't need to use @connect to access fetched data caz it's already in component's props.

Sure if you want access to another state values, you can use both @asyncConnect and @connect to access 'flows' and other state values respectively.

I want to check the state for my "flows" part of the global state, see if it is present and if not fetch it from the external api

You can implement your logic right inside function you have under 'promise' key.

@asyncConnect([{
   key: 'flows',
    promise: ({ store: { dispatch, getState } }) => {
        return dispatch(fetchCollections());
    }
}])

store is passed as param to this function so you can check store.getstate() to know if data has already been loaded.
According to your reducers config, you should check for store.getState().reduxAsyncConnect['flows']. So if it wasn't yet loaded you can return dispatch(fetchCollections()) like you do now. If data has been loaded you can either return existing data or don't return anything.

Hope this helps.