0

Very new to React and redux. I'm trying to add a file drag and drop feature to my React app but struggling with how that works using redux toolkit's createSlice function.

I keep getting 'TypeError: Cannot read property 'fileList' of undefined'. I think it's because I've messed up with the addFilesToList reducer in searchSlice.js below.

Any help would be massively appreciated. Please see my code below:

searchSlice.js

import { createSlice } from '@reduxjs/toolkit'


export const searchSlice = createSlice({
    name:'search',
    initialState: {
        fileList: [],
        inDropZone: false, 
         
    },

    reducers: {

        addToDropZone: (state) => {
            return state.inDropZone = true
        }
        ,
        
        addFilesToList: (state, e) => {
            return state.fileList = [...e.dataTransfer.files]
        }
    }
})

export const { addToDropZone, addFilesToList } = searchSlice.actions

export default searchSlice.reducer

DragDrop.js

import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { addToDropZone, addFilesToList } from './searchSlice.js'
import DragArea from './DragArea.js'
import TableArea from './TableArea.js'

//import img from './components/images/drag.PNG'//


const DragDrop = (props) => {

    const files = useSelector((state) => state.searchSlice.fileList)
    const inDropZone = useSelector((state) => state.searchSlice.inDropZone)
    const dispatch = useDispatch()
    //const { data, dispatch } = props//


    const handleDragEnter = (e) => {
        e.preventDefault();
        e.stopPropagation();

        dispatch(addToDropZone());
    };
    const handleDragLeave = (e) => {
        e.preventDefault();
        e.stopPropagation();
    };
    const handleDragOver = (e) => {
        e.preventDefault();
        e.stopPropagation();
        e.dataTransfer.dropEffect = 'copy';
        dispatch(addToDropZone());
    };
    const handleDrop = (e) => {
        e.preventDefault();
        e.stopPropagation();

        dispatch(addFilesToList());
        dispatch(addToDropZone());

        if (files && files.length > 0) {
            const existingFiles = files.map(f => f.name)
            files = files.filter(f => !existingFiles.includes(f.name))


        }

    };


    if (inDropZone === true && files.length === 0) {
        return(
                <div className = "drag-and-drop" 
                    onDrop={handleDrop}
                    onDragOver= {handleDragOver}
                    onDragEnter={handleDragEnter}
                    onDragLeave={handleDragLeave}>
                    <DragArea  />
                </div>
        )
    } else {
        return(
            <div className = "table-area" 
                onDrop={handleDrop}
                onDragOver= {handleDragOver}
                onDragEnter={handleDragEnter}
                onDragLeave={handleDragLeave}>
                <TableArea data = {files} />
        </div>
        )
    } 
}


export default DragDrop;
goodaytar
  • 75
  • 5

1 Answers1

0

The type of e in your addFilesToList reducer is a PayloadAction. This means its shape is like:

{
  type: “search/addFilesToList”,
  payload: valueYouPassToActionCreator
}

The valueYouPassToActionCreator is whatever you pass into the addFilesToList action creator when you dispatch it, e.g.:

dispatch(addFilesToList(valueYouPassToActionCreator))

You, however, are doing:

dispatch(addFilesToList())

Which means your the .payload property on your PayloadAction is undefined. In short, you need to pass something into the action creator.