Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it ok to mutate state directly before calling setState()?

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"???

Update

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.

like image 321
NSjonas Avatar asked Sep 16 '17 06:09

NSjonas


People also ask

Why we should not mutate state directly?

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.

Can we change state directly in React?

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.

Why are we using setState whereas not mutating the state?

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.

How do you update state immediately in React?

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.


Video Answer


2 Answers

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.

like image 100
Surender Avatar answered Oct 19 '22 12:10

Surender


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

like image 38
Roopak PutheVeettil Avatar answered Oct 19 '22 14:10

Roopak PutheVeettil