I'm using a lightweight ORM to connect my react app with an external service... This package returns objects of your model and allows you to perform operations directly against them. While this is really awesome, I'm struggle to figure out how I can include these objects in state
and still follow the "never modify state directly" tenant of react.
If I had a component that updated the account name, would it be acceptable to do something like this?
interface IAppState {
account: Account
}
class App extends React.Component<{}, IAppState> {
constructor(props) {
super(props);
this.state = {
account: new Account()
}
}
//set the new name and update the external service
public updateAccount = (newName: string)=>{
account.name = newName; //REDFLAG!!!
acc.update().then(()=>{
this.setState({ account: this.state.account })
})
}
//retrieve our account object from external service
public componentDidMount() {
const qParams = queryString.parse(window.location.search);
Account.get(qParams.externalId).then((acc)=>{
this.setState({account: acc})
})
}
render() {
return <NameEditor handleClick={this.updateAccount} account={a} />
}
}
I guess I could avoid mutating state by initiating a blank ORM object, copying the properties over, sending the update and then setting state, but this seems like a major pain.. Especially since these ORM objects can contain child ORM objects that I'd like to be able to modify as well.
Is the way I'm mutating state above "dangerous" or "bad form"???
Did some reading and it definitely seems like this is probably bad form and might be navigated elegantly using the react/addons
... However, what if the ORM call has a side effect on the object? For example, calling insert
sets the objects external id field.
So, when you mutate the state directly and call setState() with an empty object. The previous state will be polluted with your mutation. Due to which, the shallow compare and merge of two states will be disturbed or won't happen, because you'll have only one state now.
Never ever directly update/mutate state in React, as it's a bad practice and it will cause issues in your application. Also, your component will not be re-rendered on state change if you make a direct state change.
Instead, we should use setState() . One reason is, for a pure component, directly mutating state won't trigger the component re-render, which could cause some odd bugs. With setState() we can change the state without directly mutating it.
To update state in React components, we'll use either the this. setState function or the updater function returned by the React. useState() Hook in class and function components, respectively.
public updateAccount = (newName: string)=>{
//account.name = newName; //REDFLAG!!!
// You can use the below code to update name after it is updated
// on server.
// This will work because the object being passed here
// will be merged with Component state.
acc.update().then(()=>{
this.setState({account: {name : newName}})
})
}
Directly modifying state is not recommended as react will not come to know of the change and it will not cause a rerender.
All the diffing happens on Virtual DOM and react only updates the change attributes to Browser DOM. You can read more about the react diffing algorithm here.
React recommends to use immutable objects for setting state. you can either use Object.assign or immutable.js for this purpose which will make our life easier. If you mutate your state object it will affect the the performance of your react component.
You can refer the below link for more information.
https://facebook.github.io/react/docs/optimizing-performance.html#examples
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With