DSteman
DSteman

Reputation: 1658

Redux action.type is undefined

I'm doing a small project with Redux and I'm running into the issue of an undefined action.type and I can't seem to find out what is causing it. I already cut out a lot of code to simply try to dispatch the 'LIKE' action.

My reducer looks like this:

import blogService from '../services/blogs'

const blogReducer = (state = [], action) => {
  switch (action.type) {
  case 'LIKE': {
    // const newState = state.filter(x => x)
    // const likedBlogIndex = state.findIndex(x => x.id === action.data.id)
    // newState[likedBlogIndex] = { ...state[likedBlogIndex], likes: newState[likedBlogIndex].likes + 1 }
    return action.type
  }
  case 'INIT':
    return action.data
  default: return state
  }
}

export const initBlogs = () => {
  return async dispatch => {
    const blogs = await blogService.getAll()
    dispatch({
      type: 'INIT',
      data: blogs.sort((a, b) => (b.likes - a.likes))
    })
  }
}

export const likeBlog = () => {
  return async dispatch => {
    // const likedBlog = await blogService.update(blog)
    dispatch({
      type: 'LIKE',
      // data: { id: likedBlog.id, votes: likedBlog.votes }
      data: ''
    })
  }
}

export default blogReducer

And the component from where the function is called that dispatches the action looks like this:

/* eslint-disable linebreak-style */
import React from 'react'
import Togglable from './Togglable'
import { useSelector, useDispatch } from 'react-redux'
import likeBlog from '../reducers/blogReducer'

const BlogList = ({ handleDelete }) => {
  const blogs = useSelector(state => state.blogs)
  const dispatch = useDispatch()
  return(
    blogs.map(blog =>
      <div key={blog.id}>
        <div className='blog'>
          {blog.title} {blog.author}
        </div>
        <Togglable showLabel='show' hideLabel='hide'>
          <p>
            <b>url:</b> {blog.url}
          </p>
          <p>
            <b>likes:</b> {blog.likes} <button onClick={() => dispatch(likeBlog())}>Like</button>
          </p>
          <p>
            <b>id:</b> {blog.id}
          </p>
          <button onClick={(e) => handleDelete(e, blog)}>remove</button>
        </Togglable>
      </div>
    )
  )
}
export default BlogList

For the record: the error I'm facing is that action.type at line 4 of my reducer is undefined. I really hope someone spots the mistake. Thanks.

Upvotes: 0

Views: 1489

Answers (1)

phry
phry

Reputation: 44276

In this line you take the default export from the blogReducer file and name it likeBlog

import likeBlog from '../reducers/blogReducer'

But the default export is the reducer, so you are renaming the reducer and then using it as an action creator.

What you really want is import the named export from that file, like

import { likeBlog } from '../reducers/blogReducer'

that should work.

PSA: you are writing a pretty outdated style of redux here, it is very possible that you are following an outdated tutorial and will learn a style of redux that required multiple times the amount of code modern redux would requre. Please follow the official redux tutorials found at https://redux.js.org/tutorials/index

Upvotes: 2

Related Questions