Somename Somename - 3 years ago 362
React JSX Question

state.findIndex is not a function error with findIndex

I'm passing the

id
of the object as the
action.payload
to the reducer to modify the object.

Reducer:

const initialState = {
posts: [
{id:1, name:'post1', number:11},
{id:2, name:'post2', number:22},
{id:3, name:'post3', number:33}
]
}

export default function newData (state = initialState, action) {

switch (action.type) {

case "updateNumber": {

// find object to update
const index = state.findIndex(({ id }) => id == action.payload);

if (index > -1 ) {
const toIncrement = state[index];
const number = toIncrement.number++;

// create new object with existing data and newly incremented number
const updatedData = { ...toIncrement, number };

// return new array that replaces old object with incremented object at index
return [...state.slice(0, index), updatedData, ...state.slice(index + 1)];
}

// return state if no object is found
return state;
}

default:
return state
}
}


But I'm getting error:
state.findIndex is not a function
. How to find the index of the element in the
posts
array? console.log actions is giving me
{type: "updateNumber", payload: 2}
where
payload
is the element pressed.

UPDATE1:

export default function newData (state = initialState, action) {

switch (action.type) {

case "updateNumber": {

// find object to update
const index = state.posts.findIndex(({ id }) => id == action.payload);

if (index > -1 ) {
const toIncrement = state.posts[index];
const number = toIncrement.posts.number++;

// create new object with existing data and newly incremented number
const updatedData = { ...toIncrement, number };

// return new array that replaces old object with incremented object at index
return [...state.posts.slice(0, index), updatedData, ...state.posts.slice(index + 1)];
}

// return state if no object is found
return state;
}

default:
return state
}
}


So this is supposed to return the
posts
with updated
number
in the state, right?

Answer Source

Your initialState is an object.

I think you meant

state.posts.findIndex(({ id }) => id == action.payload);  

Or maybe change the initialState to

const initialState = [
    {id:1, name:'post1', number:11},
    {id:2, name:'post2', number:22},
    {id:3, name:'post3', number:33}
  ]

Edit
As a followup to your edit,
After your change, Now you can do:

const number = toIncrement.number++;

As totalIncrement will hold an object like this for example:

{id:1, name:'post1', number:11}  

Edit #2
I think you are mutating the state which is not allowed in redux.
Try changing this:

if (index > -1 ) {
      const toIncrement = state.posts[index];
      const number = toIncrement.posts.number++;  

To this:

if (index > -1 ) {
      const toIncrement = {...state.posts[index]};
      const number = toIncrement.posts.number + 1; // i hope this is a number and not a string!

Another thing, Your initial state is an object but your reducer returns an array.
Change this line:

// return new array that replaces old object with incremented object at index
      return [...state.posts.slice(0, index), updatedData, ...state.posts.slice(index + 1)];  

To this line:

// return new array that replaces old object with incremented object at index
      return { posts: [...state.posts.slice(0, index), updatedData, ...state.posts.slice(index + 1)]};
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download