Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 760
Brandon Baum Avatar asked Apr 13 '16 03:04

Brandon Baum


People also ask

What happens when we dispatch an action in Redux?

The app code dispatches an action to the Redux store, like dispatch({type: 'counter/incremented'}) The store runs the reducer function again with the previous state and the current action , and saves the return value as the new state.

What happens when we dispatch an action in React?

Each time an action is dispatched, every connect ed component will be notified, and as a result all of the selectors used by those connect ed components must be re-evaluated. To say that another way: each time an action is dispatched, every selector in the app must be re-evaluated.

How do I use the dispatch in Redux?

dispatch() , you can also dispatch actions by mapping it with props using the mapDispatchToProps() method and passing it to the connect() function for a cleaner syntax. Alternatively, you can explore libraries like Redux Saga and learn more about dispatching Async actions in its official documentation.

Which functions are used to trigger an action in Redux?

Redux includes a utility function called bindActionCreators for binding one or more action creators to the store's dispatch() function. Calling an action creator does nothing but return an object, so you have to either bind it to the store beforehand, or dispatch the result of calling your action creator.


2 Answers

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

like image 182
Ahmed Elkoussy Avatar answered Sep 24 '22 00:09

Ahmed Elkoussy


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.

like image 23
Vadim Avatar answered Sep 24 '22 00:09

Vadim