Stephan Bakkelund Valois
Stephan Bakkelund Valois

Reputation: 1072

react redux action not calling reducer

I cant for the life of my get one of my actions to call the reducer. I've written multiple other actions and reducers in this app, which works perfectly.

It is the beginning of a filter function. I have a text input field, where I constantly keep track of the input field state, and dispatch the field value to the redux action. I have a console.log inside the action, which logs every keypress properly.

What I cant seem to understand, is why the reducer isn't called at each keypress. I've tried multiple console.log's inside the reducer, however none of them gets logged with keypresses.

The first console.log inside the reducer is called when I refresh the page. if I try to log action.type instead, I get:

@@redux/PROBE_UNKNOWN_ACTION1.0.i.0.0.9

If I try the same in any of the other reducers I've written in the same app, I get the appropriate type logged out.

Some code:

Filter Component:

import React, { useState } from 'react'
import { useDispatch } from 'react-redux';
import { filterAnecdotes } from '../reducers/filterReducer';

const Filter = () => {
  const [value, setValue] = useState("");

  const handleChange = (e) => {
    setValue(e.target.value)
  }

  useDispatch(filterAnecdotes(value));
  const style = {
    marginBottom: 10
  }

  return (
    <div style={style}>
      filter <input onChange={handleChange} />
    </div>
  )
}

export default Filter

Reducer and action: Here, I haven't figured out how to get the state of all anecdotes, and what to actually return. For now, I'm just trying to have it get called properly.

const filterReducer = (state = null, action) => {

  // These logs only get logged on refresh.
  // The action.type should be 'SEARCH', but is not.
  console.log("From filterReducer")
  console.log(action.type)

  switch(action.type) {
    case 'SEARCH':

      // This is not called at all.
      console.log(action.type, action.data)

      return action.data;
    default:
      return state
  }
}

export const filterAnecdotes = (filter) => {
  console.log(filter);
  return {
    type: 'SEARCH',
    data: filter
  }
}

export default filterReducer;

Example of a redux file that actually works:

const reducer = (state = [], action) => {
  console.log(state, action)
  switch(action.type){
    case 'NEW_ENTRY_NOTIFICATION':
    console.log(action.type)
      return [...state, action.data]
    case 'NEW_VOTE_NOTIFICATION':
      return [...state, action.data]
    case 'HIDE_NOTIFICATION':
      return []
    default:
      return state
  }
}

export const createNewEntryNotification = (notification) => {
  return {
    type: 'NEW_ENTRY_NOTIFICATION',
    data: notification
  }
}

export const createNewVoteNotification = (notification) => {
  return {
    type: 'NEW_VOTE_NOTIFICATION',
    data: notification
  }
}

export const hideNotification = () => {
  return {
    type: 'HIDE_NOTIFICATION'
  }
}


export default reducer

App component (should be irrelevant)

import React from 'react';
import NewEntry from './components/AnecdoteForm'
import AnecdoteList from './components/AnecdoteList'
import Notification from './components/Notification'
import Filter from './components/Filter';

const App = () => {

  return (
    <div>
      <h2>Anecdotes</h2>
      <Filter />
      <Notification />
      <AnecdoteList />
      <NewEntry />
    </div>
  )
}

store (should be irrelevant)

import anecdoteReducer from './anecdoteReducer';
import notificationReducer from './notificationReducer';
import filterReducer from './filterReducer';
import { combineReducers } from 'redux'


const reducer = combineReducers({
  anecdotes: anecdoteReducer,
  notifications: notificationReducer,
  filters: filterReducer,
});


export default reducer

index.js (should also be irrelevant)

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App from './App'
import reducer from './reducers/store'

const store = createStore(reducer)

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)


export default App

I'll be happy to provide more information if needed. This is for a project from fullstackopen.

Upvotes: 1

Views: 1364

Answers (2)

CFLS
CFLS

Reputation: 355

the use of useDispatch is misunderstood. Link for reference: https://react-redux.js.org/api/hooks#usedispatch

You should create a dispatch from useDispatch:

const dispatch = useDispatch();

dispatch(filterAnecdotes(value));

Upvotes: 1

Benjam&#237;n Escobar
Benjam&#237;n Escobar

Reputation: 242

Try to instantiate useDispatch like this after const [value, setValue] = useState("");

const dispatch = useDispatch();

And then use the intance to dispatch the action

dispatch(filterAnecdotes(value));

Upvotes: 4

Related Questions