27mdmo7sn
27mdmo7sn

Reputation: 509

I can't update state for array item in react native

I have this variable

const routes = [{data : 'Home' , icon : 'home' , keep:true , txt:'Home'} , {data : 'NECard' , icon : 'card' , keep:true , txt:'Your Card'} , {data : 'Notifications' , icon : 'notifications' , color : '#EB4D4B' , count : 27 , keep:true , txt:'Notifications'} , {data : 'Requests' , icon : 'contacts' , color : '#0097E6' , count : 8 , keep:true , txt:'Requests'} , {data : 'Saved' , icon : 'bookmark' , color : '#FBC531' , count : 51 , keep:true , txt:'Saved'} , {data : 'Logout' , icon : 'ios-exit' , keep:true , txt:'Logout'}];

I set the state in the constructor

this.state = {routes : routes};

also after mounting the component I run this

componentDidMount()
  {
    this.fetchNotReadedNotis();
  }

the last step

    async fetchNotReadedNotis()
    {
       this.state.routes[2].count = 392;
       this.forceUpdate();
    }

using setState is also not working

 async fetchNotReadedNotis()
        {
           var rts = this.state.routes;
           rts[2].count = 392;
           this.setState({routes:rts});
        }

the expected is to set the routes[2] count property to 392

but no changes at all , it still 27

is there something wrong with my codes?

Upvotes: 0

Views: 1130

Answers (3)

Tholle
Tholle

Reputation: 112787

You should not mutate state directly in React. You should use setState to update the state.

Example

class App extends React.Component {
  state = {
    routes: [
      { data: "Home", icon: "home", keep: true, txt: "Home" },
      { data: "NECard", icon: "card", keep: true, txt: "Your Card" },
      {
        data: "Notifications",
        icon: "notifications",
        color: "#EB4D4B",
        count: 27,
        keep: true,
        txt: "Notifications"
      },
      {
        data: "Requests",
        icon: "contacts",
        color: "#0097E6",
        count: 8,
        keep: true,
        txt: "Requests"
      },
      {
        data: "Saved",
        icon: "bookmark",
        color: "#FBC531",
        count: 51,
        keep: true,
        txt: "Saved"
      },
      { data: "Logout", icon: "ios-exit", keep: true, txt: "Logout" }
    ]
  };

  componentDidMount() {
    this.fetchNotReadedNotis();
  }

  fetchNotReadedNotis = async () => {
    this.setState(previousState => {
      const routes = [...previousState.routes];

      return {
        routes: [
          ...routes.slice(0, 2),
          { ...routes[2], count: 392 },
          ...routes.slice(3)
        ]
      };
    });
  };

  render() {
    return (
      <div>
        {this.state.routes.map(route => (
          <div key={route.data}>
            {route.data} {route.count}
          </div>
        ))}
      </div>
    );
  }
}

Upvotes: 0

reisdev
reisdev

Reputation: 3383

You should update state directly. Do as below:

fetchNotReadedNotis = async () => {
   var routes = Object.assign([],this.state.routes)
   routes[2].count = 392
   this.setState({routes: routes},() => { this.forceUpdate() })
}

Detail: Your fetchNotReadedNotis wasn't binded to your component, so it can't mutate the state of it. The this reference inside your method wasn't your component. Now, doing the fetchNotReadedNotis = async () => {}, it is binded to your component, and then, it will mutate the state properly.

class App extends React.Component {
    constructor(props){
      super(props)
      this.state = {
        routes: [{data : 'Home' , icon : 'home' , keep:true , txt:'Home'} , {data : 'NECard' , icon : 'card' , keep:true , txt:'Your Card'} , {data : 'Notifications' , icon : 'notifications' , color : '#EB4D4B' , count : 27 , keep:true , txt:'Notifications'} , {data : 'Requests' , icon : 'contacts' , color : '#0097E6' , count : 8 , keep:true , txt:'Requests'} , {data : 'Saved' , icon : 'bookmark' , color : '#FBC531' , count : 51 , keep:true , txt:'Saved'} , {data : 'Logout' , icon : 'ios-exit' , keep:true , txt:'Logout'}]
      }
    }
    componentDidMount(){
        this.fetchNotReadedNotis();
    }
    fetchNotReadedNotis = () => {
       var routes = Object.assign([],this.state.routes)
       routes[2].count = 392
       this.setState({routes: routes},() => { this.forceUpdate()})
    }
    render() {
        return(
        <div>
           {this.state.routes.map(route => <p> {route.data} {route.count}</p>)}
        </div>
      )
    }
}

ReactDOM.render(<App/>,document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"> </div>

Upvotes: 0

Dinesh undefined
Dinesh undefined

Reputation: 5546

You should use this.setState() function to update react state. You should not mutate state directly. Read Docs here

Upvotes: 2

Related Questions