Reputation: 509
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
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
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
Reputation: 5546
You should use this.setState()
function to update react state. You should not mutate state directly. Read Docs here
Upvotes: 2