redux action "is not a function" when dispatched from component

Brandon Baum picture Brandon Baum · Apr 13, 2016 · Viewed 18.5k times · Source

I am trying to create an app with a CSV upload. When a CSV is uploaded it will change the state and then I will parse from CSV to JSON and do stuff with it. The idea is to upload a file and update state. Once that state is updated I would pass the CSV to a Meteor.method to parse to JSON. I am using Meteor, React and Redux. I have a component that handles the upload, an action and a reducer. All of the files are below - I am new to Meteor, React and Redux and I cannot figure out for the life of me why this is not working. I don't think that I am fully understanding what I am trying to accomplish. Any suggestions are welcome.

ERROR - Uncaught TypeError: fileUpload is not a function UploadCSV.jsx

// ACTIONS - fileUpload.js
export default function fileUpload(file) {
  return {
    type: 'FILE_UPLOAD',
    file
  };
}



//REDUCERS - upLoad.js
export default function upLoad(state = 'NO_FILE', action = {}) {
  switch (action.type) {
    case 'FILE_UPLOAD':
      return action.file;
    default:
      return state;
  }
}



//COMPONENTS - UploadCSV.jsx
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import Dropzone from 'react-dropzone';
import { RaisedButton } from 'material-ui';
import { Colors } from 'material-ui';
import fileUpload from '../actions/fileUpload.js';
import { uploadCSV } from '../actions/uploadCSV.js';

class UploadCSV extends Component {
  render( dispatch, file, fileUpload ) {
    const onDrop = (file) => {
      console.log(file);
    }
    const upLoad = () => {
      this.props.dispatch(fileUpload(file));
    };
    return (
      <div>
        <Dropzone accept="csv"
                  onDrop={ () => {
                      return upLoad();
                    }}>
          <div>Click or drop files here.</div>
        </Dropzone>
      </div>
    )
  }
}

export default connect()(UploadCSV);

I don't understand why fileUpload is "not a function" if it is an action and it is being imported.? If anyone can lend a hand I would appreciate it.

Thanks!

Answer

Ahmed Elkoussy picture Ahmed Elkoussy · Nov 27, 2018

One reason for this problem that is easy to miss is the following:

If we define the component class with a default export & a named export like this:

// named export
export class MyComponent extends React.Component{      
.......
function mapDispatchToProps(dispatch){
    return bindActionCreators({reduxAction},dispatch)
}
// default export
export default connect(null,mapDispatchToProps)(MyComponent); 

Then we should import the default export not the named export:

This imports the default export & shall work correctly with redux

import MyComponent from "./thePath"

This imports the named export & won't work with redux

import {MyComponent} from "./thePath"

The reason

We have to import the default export when rendering the component in order to use the redux connect() higher order function that we have exported.

Sometimes if you just depend on the editor auto import, it will import the named export (which doesn't have the redux connect) & therefore will give that error

Bottom line

Make sure to import the default export (without braces) when calling the component to use redux connect() correctly