0

I've tried to change this so many ways, no matter how it's done/explained on other Stack Overflow posts. I have an array of objects, and I am trying to map/loop through the array move one of the objects to the front of the array.

Here's what I've got:

const [users, setUsers] = useState<User[]>([]);
const [primaryUser, setPrimaryUser] = useState<User>({
  id: 0;
  first_name: "",
  last_name: ""
})

useEffect(() => {
  users.map((user, i) => {
    if(user.id === 12345) {
      users.splice(i, 1);
      users.unshift(user)

      setPrimaryUser(user);
    }
  });

  setUsers(users);
}, [])

Whether I map as shown above or use a for loop, I always end up getting the following error: TypeError: Cannot assign to read only property 'x' of object '[object Array]'

Any suggestions/help is greatly appreciated. Thanks in advance!

6
  • if(user.id = 12345) this is assignment, not equality. Moreover, you should probably avoid mutating users via .splice() and .unshift(). Also, as a side note, please don't use .map as a simple iteration. If you're not doing a mapping operation, use .forEach or a simple loop. Commented Nov 12, 2020 at 21:44
  • Thanks, I copied it over incorrectly. I have it as if(user.id === 12345) {. Also, I've tried a forEach and for loop. Still getting the same error every time. Commented Nov 12, 2020 at 21:51
  • Then the issue is with mutating the array. You should never mutate state directly with React and this is exactly the problem you get here. Commented Nov 12, 2020 at 21:53
  • I've even tried making a copy of the state - let tempUsers = users, mutating that, setting it - setUsers(tempUsers) and still the same thing. Commented Nov 12, 2020 at 21:54
  • 1
    let tempUsers = users will not make a copy of the array! Copy array by value Commented Nov 12, 2020 at 21:55

2 Answers 2

1

I see the code is used in React, so it is best to avoid modifying the users array in place (for example with .unshift() or .splice()) as React will not see the difference and will not re-render.

It is common practice in React to create new value for the previous one.

I think you can achieve the goal by filtering the users array twice (filter method creates a copy without affecting the original):

  • users with id 12345 - expecting just one and and store it in primaryUser variable
  • users with id not 12345

and combining those arrays:

useEffect(() => {
  const primaryUserID = 12345;
  const [ primaryUser ] = users.filter(user => user.id === primaryUserID)
  setPrimaryUser(primaryUser);

  // Construct array from 'primaryUser' and the rest of users
  const newUsers = [
     primaryUser,
     ...users.filter(user => user.id !== primaryUserID),
  ];
  setUsers(newUsers);
}, [])
Sign up to request clarification or add additional context in comments.

1 Comment

Here's great article about JS array methods, it explains filter/map/reduce using good examples telerik.com/blogs/…
0

Thanks to both VLAZ and Vitalii (great article), I was able to get it working. Here was my solution:

useEffect(() => {
  let tempUsers = [...users];

  tempUsers.map((user, i) => {
    if(user.id === 12345) {
      tempUsers.splice(i, 1);
      tempUsers.unshift(user)

      setPrimaryUser(user);
    }
  });

  setUsers(tempUsers);
}, [])

THANK YOU!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.