Jonathan
Jonathan

Reputation: 469

componentDidMount() how to do a setState()

I'm trying to migrate to React 17 and I want to change

componentWillMount () {
    this.setState({ model: this.props.formModel })
}

to React 17

componentDidMount () {
    this.setState({ model: this.props.formModel })
}

But I have this error in componentDidMount

Do not use setState in componentDidMount

Any suggestion?

Upvotes: 0

Views: 2052

Answers (5)

Senthil
Senthil

Reputation: 777

You don't use componentDidMount(). You can use componentDidUpdate().

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.state.model !== prevProps.formModel) {

     this.state({ model : prevProps.formModel})
  }
}

Upvotes: 1

Toan Quoc Ho
Toan Quoc Ho

Reputation: 3378

About why you shouldn't call setState inside componentDidMount, you can take a look at React document

You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. In most cases, you should be able to assign the initial state in the constructor() instead. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.

You can set the state from props in your constructor like this:

class ReactComp(Component):
    constructor(props) {
        super(props);

        this.state = {
            model: props.formModel
        }
    }

But this will work for the first time React mount this component for you. When the data changed, the state won't reflect. So I refer to use getDerivedStateFromProps instead, this is also a recommend way to implement due to componentWillMount will be deprecated in a couple of releases.

class ReactComp(Component):
    constructor(props) {
        super(props);
    }

    static getDerivedStateFromProps(props, state) {
        if (props.formModel !== state.formModel) {
            return {
                formModel: props.formModel,
            };
        }

        // Return null to indicate no change to state.
        return null;
    }

Hope that helps!

Upvotes: 1

N. Henoc HOUNSA
N. Henoc HOUNSA

Reputation: 169

Already we must understand that it has a difference between the two : componentWillMount and componentDidMount

componentWillMount is called before the render and
componentDidMount is much more used to update the dom

componentDidMount is the perfect place to make your setState()
you will rarely need to use componentWillMount for this kind of action.

maybe you could show more your code so that we can see why you have this error :

Do not use setState in componentDidMount

it's may be because of your linter as christian say

Upvotes: 1

I reckon this warning is from ESLint. It's a rule that was implemented back in the days when calling setState in componentDidMount caused visible render flash. This is no longer the case so you can just disable the rule.

However, if you're setting an initial state, this should happen in your constrcutor. See here:

https://reactjs.org/docs/react-component.html#componentdidmount

You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. In most cases, you should be able to assign the initial state in the constructor() instead. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.

Upvotes: 2

Jonathan
Jonathan

Reputation: 469

Just you have to use

state = ({ model: this.props.formModel })

don't need to call componentDidMount

Upvotes: 0

Related Questions