1

I'm doing a simple React app where any user introduce a text in the input text, and automatedly it will update the state in the store. It is very simple practice of React but I'm getting very struggle and frustrated with this error because I tried everything but I'm still having the same problem.

I am using "react-redux" and "@reduxjs/toolkit" dependencies. I tried everything, I checked and compare similar examples and solutions to similar problems, I remade the app from the scratch just to make sure that there is not any problem with different versions of the dependencies, and I keep my code very simple trying to make it work, but it doesn't.

I hope any of you could give me an advice or solution. Thank You!!

Error

TypeError: Object(...) is not a function
handleChange
C:/Users/Ruben/Desktop/Projects/React/reddit2/reddit/src/features/search/SearchBar.js:14
  11 | 
  12 | 
  13 |  const handleChange = (e) => {
> 14 |    dispatch(setSearchTerm(e.target.value))
     | ^  15 |  }
  16 | 
  17 | 
View compiled
▶ 19 stack frames were collapsed.
This screen is visible only in development. It will not appear if the app crashes in production.
Open your browser’s developer console to further inspect this error.  Click the 'X' or hit ESC to dismiss this message.

Those are the files:

SearchBar Component

import React from "react";
import {useDispatch, useSelector} from "react-redux";
import {setSearchTerm, selectSearchTerm} from "../search/searchSlice";


export const SearchBar = () => {
  
  
  const dispatch = useDispatch();
  const term = useSelector(selectSearchTerm);


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


  return(
    <div>
      <input
        id="search"
        type="text"
        value={term}
        onChange={handleChange}
        placeholder="Introduce your Topic"
        />
    </div>
  );
};

searchSlice

import {createSlice} from "@reduxjs/toolkit";


export const searchSlice = createSlice({
  name: 'search',
  initialState: '',
  reducer: {
    setSearchTerm: (state, action) => {state.search = action.payload},
  }
});

export const {setSearchTerm} = searchSlice.actions;

export const selectSearchTerm = (state) => state.search;

export default searchSlice.reducer;

Store

import {configureStore} from "@reduxjs/toolkit";
import searchReducer from "../features/search/searchSlice";

export default configureStore({
  reducer: {
    search: searchReducer,
  },
});

Index

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from "react-redux";
import './index.css';
import App from '../src/App/App';
import reportWebVitals from './reportWebVitals';
import store from "../src/App/store";

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

Package.json

{
  "name": "reddit",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@reduxjs/toolkit": "^1.5.1",
    "@testing-library/jest-dom": "^5.13.0",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-redux": "^7.2.4",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.2"
  },
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • 1
    There are multiple things to debug. `onChange={(e)=>handleChange(e.target.value)}` , `const handleChange = (value) => { dispatch(setSearchTerm(value)) }` . Read about synthetic events. Can you add code for setSearchTerms? – Anglesvar Jun 04 '21 at 18:20
  • Thank you for your comment Anglesvar, but still the same problem. setSearchTerm is the action creator of the searchSlice reducer, the file is posted. – Ruben Gonzalez Jun 04 '21 at 18:38
  • `setSearchTerm` is actually taking two parameters according to your code. `(state, action)` . So this is the reason the error is thrown. I would suggest you to look into action, reducer, store concept thoroughly. Hope it help! – Anglesvar Jun 04 '21 at 18:48
  • 1
    @Anglesvar `setSearchTerm` is the name of the reducer function in the slice, which *does* take the normal `state` and `action` arguments, ***however*** redux-toolkit builds action creator functions for export (i.e. `searchSlice.actions`), which take only a single argument (i.e. `payload`) by default. – Drew Reese Jun 04 '21 at 18:59
  • Thank you Anglesvar, but I had a second look, and it looks right the code, I don't know what I'm missing. Thank you @DrewReese for your comment as well. – Ruben Gonzalez Jun 04 '21 at 19:09
  • I think the problem is with useDispatch, because I checked other projects with the same goal, and looks the same as mine. – Ruben Gonzalez Jun 04 '21 at 19:18

1 Answers1

1

Issues

  1. You've a typo in the createSlice, the proper key is reducers, with an "s", not reducer. This is causing the slice actions to actually be undefined.
  2. Your state isn't quite correct. It's not a draftable object.

Solution

Correct the reducer key and provide correct state.

export const searchSlice = createSlice({
  name: "search",
  initialState: { search: "" }, // <-- object state
  reducers: {
    setSearchTerm: (state, action) => {
      state.search = action.payload; // <-- update property
    }
  }
});

export const { setSearchTerm } = searchSlice.actions;

export const selectSearchTerm = (state) => state.search.search; // <-- select property

export default searchSlice.reducer;

Edit react-usedispatch-typeerror-object-is-not-a-function-handlechange

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Thank You very much, Drew Reese, finally after the whole day trying, changing, looking...., you fixed my problem, thank you very much not only for fixing my problem, I wasn't sure about the initial state has to be an object, and I never will forget to put an 's' again in reducers........:P – Ruben Gonzalez Jun 04 '21 at 19:48