Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Uncaught TypeError: Cannot read property 'type' of undefined" and unclear what it is related to

I originally thought this was an issue with react-redux, axios, lodash, and/or react-dropzone; however, files are uploading fine, but this error still triggers. (Even though it is says "failed" in console, the files are being posted to the server).

I am starting to think the issue might be related to react-router-redux based on what I read here:

https://github.com/reactjs/react-router-redux/issues/182

However, the suggestions are not working for me.

Anyway, I am getting an Uncaught TypeError: Cannot read property 'type' of undefined that I can't really tell what is causing it or how to resolve it. Here are some screenshots of the errors:

undefinedline

So here is what should be relevant to react-router. Just not sure what is going on.

The entry point:

// ./react/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import { routerMiddleware, ConnectedRouter } from 'react-router-redux';

import createHistory from 'history/createBrowserHistory';

// Render on every route
import App from './components/app';
import Navbar from './containers/global/navbar';
import Footer from './containers/global/footer';

// Reducers 
import rootReducer from './reducers';

// SCSS for the project
import styles from '../assets/scss/main.scss';

// IE polyfill error fix
require('es6-promise').polyfill();
var axios = require('axios');

const history = createHistory();

const initialState = {};
const enhancers = [];
const middleware = [thunk, routerMiddleware(history)];

if (process.env.NODE_ENV === 'development') {
    const devToolsExtension = window.devToolsExtension

    if (typeof devToolsExtension === 'function') {
        enhancers.push(devToolsExtension())
    }
}

const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers);
const protectedRoute = compose(Timers, RequireAuth);

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

ReactDOM.render(
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <div>
                <Navbar />
                <App />
                <Switch>
                      // various routes go here...
                </Switch>
                {/*<Footer />*/}
            </div>
        </ConnectedRouter>
    </Provider>
    , document.querySelector('.container'));

The global reducers and those that pertain to the action that triggers the error.

// ./react/reducers/index.js
import { combineReducers } from 'redux';
import { reducer as form } from 'redux-form';
import { routerReducer } from 'react-router-redux';
import documentReducer from './documents';

const rootReducer = combineReducers({
    form,
    router: routerReducer,
    documents: documentReducer,
});

export default rootReducer;

// ./react/reducers/documents.js
import {
    DOCUMENTS
} from '../actions/documents';

export default function(state = {}, action) {
    switch(action.type) {
        case DOCUMENTS:
            return { 
                ...state, 
                survey_id: action.payload.survey_id, 
            };
        default:
            return state;
    }

    return state;
}

Finally, the action that is being called when the error is raised. One important thing to point out: the error does not occur when the the axios.post is not in _.map (actually any kind of array iteration). However, that only sends one file which is not the behavior I am after.

// ./react/actions/documents.js
import _ from 'lodash';
import axios from 'axios';
import { push } from 'react-router-redux';
import { ROOT_URL } from '../../config/config.json';

// Establish the different types
export const DOCUMENTS = 'documents';

export function submitDocument(files) {
    const uploaders = _.map(files, f => {
        const formData = new FormData();

        formData.append('file', f);

        return axios.post(
            `${ROOT_URL}/api/documents/fileupload`,
            formData,
            { headers: 
                { 
                    'content-type': 'multipart/form-data',
                    'Authorization': 'JWT ' +  sessionStorage.getItem('token')
                }
            }            
        )

    });

    axios.
        all(uploaders)
        .then(response => {
            console.log('Success');
        })
        .catch(error => {
            console.log('Failed');
        })
}

The container that calls the action would probably be helpful as well:

// ./react/containers/documents/submit_documents.js
import _ from 'lodash';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { submitDocument } from '../../actions/documents';
import Dropzone from 'react-dropzone';

class SubmitDocuments extends Component {

    constructor() {
        super();
        this.state = {
            filesToBeSent: [],
            filesPreview: [],
        }

        this.handleClick = this.handleClick.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.onDrop = this.onDrop.bind(this);
    }

    handleSubmit(event) {
        event.preventDefault();
        this.props.submitDocument(this.state.filesToBeSent);
    }

    onDrop(acceptedFiles) {
        var filesToBeSent = this.state.filesToBeSent;       
        _.map(acceptedFiles, f => {
            filesToBeSent.unshift(f);
        });

        filesToBeSent = _.uniqBy(filesToBeSent, 'name');

        var filesPreview = [];

        _.map(filesToBeSent, i => {
            filesPreview.unshift(
                <div key={i.name}>
                    <h5>{i.name} - {i.size} bytes</h5>
                </div>
            )            
        });

        this.setState({
            filesToBeSent,
            filesPreview
        });
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <div className='panel panel-default'>
                    <div className='panel-heading'>
                        <h4><strong>Submit Documents</strong></h4>
                    </div>

                    <div className='panel-body'>
                        <Dropzone className='dropzone' onDrop={this.onDrop}> 
                            <h3>Click to add files or drag files here to upload</h3>
                        </Dropzone>
                        {this.state.filesPreview}
                        <button type='submit' disabled={this.state.filesPreview.length < 1} className='btn btn-primary'>Submit</button>
                        <button type='button' className='btn btn-danger' onClick={this.handleClick}>Cancel</button>
                    </div>
                </div>
            </form>
        ); 
    }
}

function mapStateToProps(state) {
    return {
        survey_id: state.documents.survey_id
    }
}

export default connect(mapStateToProps, { submitDocument })(SubmitDocuments);

Also, because webpack is mentioned in the error, here is the config for it:

var path = require('path')
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
var ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = {
  context: __dirname,

  entry: [
    '../react/index'  
  ],

  output: {
      path: path.resolve('./src/assets/bundles/'),
      filename: './js/[name]-[hash].js'
  },

  plugins: [
    new BundleTracker({filename: './src/config/webpack-stats.json'}),
    new ExtractTextPlugin({filename: './css/[name].[hash].css', allChunks: true})
  ],

  module: {
    loaders: [
      // {test: /\.(jpe?g|png|gif|svg)$/i, loader: "url-loader?name=img/[name].[ext]"},
      { 
        test: /\.jsx?$/, 
        exclude: /node_modules/, 
        loader: 'babel-loader',
        query: {
          presets: ["react", "es2015", "stage-1"]
        }
      },
      {
        test: /\.json$/,
        loader: ['json-loader'] 
      },
      {
        test: /\.scss$/,
        loader: ['style-loader', 'css-loader', 'sass-loader'] 
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader'
        })      
      },   
    ],
  },

  resolve: {
    extensions: ['*', '.js', '.jsx', '.gif']
  }
}

Anyway, not sure what is causing it and have been trying to resolve it for several days now. Everything works fine otherwise, it just looks unprofessional.

like image 202
cjones Avatar asked Jan 04 '18 16:01

cjones


2 Answers

In my case, LastPass extension was causing this error and not my code (onloadwff.js).
Fixed it by removing the extension.


As per lastpass-cli/issues/428#comment, you can avoid this by updating the LastPass extension settings to only run when clicked.

like image 189
Dorian Marchal Avatar answered Jan 03 '23 16:01

Dorian Marchal


Redux thunk action creators return a function with the arguments (dispatch, getState), and inside that function, you dispatch() actions when your data is available.

Your code is likely erroring because you haven't returned anything from your action creator at all. Since it's async, return the inner function:

export function submitDocument(files) {
    return function (dispatch, getState) {
        const uploaders = _.map(files, f => {
            const formData = new FormData();

            formData.append('file', f);

            return axios.post(
                `${ROOT_URL}/api/documents/fileupload`,
                formData,
                { headers:
                    {
                        'content-type': 'multipart/form-data',
                        'Authorization': 'JWT ' +  sessionStorage.getItem('token')
                    }
                }
            )

        });

        axios.
            all(uploaders)
            .then(response => {
                console.log('Success');
                dispatch({ type: DOCUMENTS, payload: ... });
            })
            .catch(error => {
                console.log('Failed');
                dispatch({ type: 'YOUR_ERROR_TYPE', payload: ... });
            })
        };
    }
like image 41
Andy Ray Avatar answered Jan 03 '23 16:01

Andy Ray