redux action "is not a function" when dispatched from component
Asked Answered
L

6

15

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!

Lass answered 13/4, 2016 at 3:1 Comment(0)
B
2

Because you defined an argument called fileUpload in your render method. Remove all of the arguments you defined in your render method. The class has closure scope over all of those imported modules, so you can reference them anywhere in the class.

Barbital answered 13/4, 2016 at 3:18 Comment(1)
Thanks - that fixed it. I saw an older react/redux example where the reducer functions were being passed into the component, but it was before the current 'render()' syntax. That is where I went wrong.Lass
O
28

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

Orchestrate answered 27/11, 2018 at 13:8 Comment(1)
Thanks for your comments here, it saved me a big headache. I thought I had not correctly setup my connect function but it was the component import on the parent component.Ding
L
4

Restart Your Application

I had the same problem simply because I forgot to restart my application. All the Redux actions are set up at first state, so the Redux Store had no idea that I had implemented a new function.

Hope this helps someone.

Laird answered 7/9, 2017 at 15:26 Comment(0)
B
2

Because you defined an argument called fileUpload in your render method. Remove all of the arguments you defined in your render method. The class has closure scope over all of those imported modules, so you can reference them anywhere in the class.

Barbital answered 13/4, 2016 at 3:18 Comment(1)
Thanks - that fixed it. I saw an older react/redux example where the reducer functions were being passed into the component, but it was before the current 'render()' syntax. That is where I went wrong.Lass
E
2

In case it helps anyone, I received TypeError: this.props.setCategories is not a function until I noticed that the value for setCategories should have been a callback:

const mapDispatchToProps = dispatch => {
    return {
        setCategories: dispatch(actionCreator.setCategories()),  // cause of error
        onAgeUp: () => dispatch(actionCreator.ageUp(1)),
        onAgeDown: () => dispatch(actionCreator.ageDown(1))
    };
};
Effulgent answered 6/4, 2019 at 23:5 Comment(0)
L
0

It appears that imported elements are case insensitive when importing them. This is what cause the same issue for me as well, so just a heads up.

Legislation answered 30/1, 2017 at 19:26 Comment(0)
D
0

I had this problem when I added new import to bindActionCreators and instead of { } I wrapped it with [ ] so check your brackets

function mapDispatchToProps(dispatch) {
  return bindActionCreators({...UserActions, ...ModalActions}, dispatch)
}
Douche answered 3/5, 2018 at 3:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.