Bill
Bill

Reputation: 5150

Javascript React: Push to an array in useState

I'm trying to store an array of strings in the state object under the key of menuHistory, im initialising it with 'first', when the page changes props.location updates, that triggers the useEffect() where I then try to push the location into the array.

The error I'm getting is..

Argument of type '{ menuHistory: number; }' is not assignable to parameter of type 'SetStateAction<{ menuHistory: string[]; }>'.
  Type '{ menuHistory: number; }' is not assignable to type '{ menuHistory: string[]; }'.
    Types of property 'menuHistory' are incompatible.
      Type 'number' is not assignable to type 'string[]'.ts(2345)
import React, {useEffect, useState} from 'react';
import {Link} from 'react-router-dom';

interface propsInterface {
    location: any; 
  }

const SideMenu: React.FC<propsInterface> = (props) => {
  const { global } = useContext(Context) as {global: any; setGlobal: React.Dispatch<React.SetStateAction<any>>};
  const [state, setState] = useState({menuHistory: ['first']});

  useEffect(() => {
    const location = props.location.pathname.split('/')[2];
    setState({menuHistory: state.menuHistory.push(location)});
  }, [props.location])

  return (
    <div className='nav'>
        <Link to={{pathname: '/my/identity'}}><div id='identity'>Identity</div></Link>
        <Link to={{pathname: '/my/accounts'}}><div id='accounts'>Accounts</div></Link>
        <Link to={{pathname: '/my/claims'}}><div id='claims'>Claims</div></Link>
        <hr/>
        <Link to={{pathname: '/my/profile'}}><div id='profile'>Profile</div></Link>
        <Link to={{pathname: '/my/password'}}><div id='password'>Password</div></Link>
        <Link to={{pathname: '/my/settings'}}><div id='settings'>Settings</div></Link>
        <Link to={{pathname: '/my/logout'}}><div id='logout'>Log out</div></Link>
  </div>
  );
}

export {SideMenu};

Upvotes: 0

Views: 3828

Answers (3)

amardeep saini
amardeep saini

Reputation: 247

You have defined {menuHistory: ['first']} which is array . Try using concat instead of push.

   setState({menuHistory: state.menuHistory.concat(location)});

Upvotes: 1

like @Clarity said, push returns index of pushed item, also this operator mutates object. Best practice is to create another array (eg. by spreading previous value, like suggested), and add a new entry there, like so:

setState({menuHistory: [...state.menuHistory, location]});

Upvotes: 2

Clarity
Clarity

Reputation: 10873

push return an index of element, use array spread to add the item:

setState(state => ({menuHistory: [...state.menuHistory, location]}));

Upvotes: 2

Related Questions