Flutter life-cycle cheatsheet for React devs

Flutter life-cycle methods meme

I struggled a lot with the flutter life-cycle methods when I started with this framework, I came from React Native development and I was still thinking in class components, where do I place my state? WHERE ARE THE PROPS, HOW DO I UPDATE STUFF and all of those things…

So In this cheat sheet, I will describe all the Flutter life-cycle methods, their React equivalent, and what they do.

If you just want to check a simple lifecycle method, here is the list:

Flutter life-cycle methods index

Mounting

Updating

Unmounting

Defining initial state

Components in Flutter are called widgets, there are two types:

  • Stateless ones
  • Stateful ones

Stateful widgets contains state, and as in React, you need to define the initial value.

In Flutter, the equivalent way is to declare your properties with values already, but if you need to do any operation first, you should use initState method. Note in this method you don’t have access to the widget context yet

React way:

// Class component

class YourComponent extends React.Component {
    state: {
        value: "initial value"
    }
    
    render() {
        return ...
    }

}

// Functional component

const YourComponent: React.FC = () => {
    const [value, setValue] = useState("initial value");
    return ...
}

Flutter way

class YourComponent extends StatefulWidget {
  WeekMealsSelector({Key key}) : super(key: key);

  @override
  _YourComponentState createState() => _YourComponentState();
}

class _YourComponentState extends State<YourComponent> {
  // This defines a state property, could have a value 
  // already
  String _value;
  
  @override
  void initState() {
    super.initState();
    // You can have your API request here, but ideally you 
    // should use a FutureBuilder
    
    // Private properties in Flutter are prefixed with _
    _value = "initial value"
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

ComponendDidMount

In Flutter, you don’t have a lifecycle method which triggers that, instead, you have the mounted property

So let’s say you want to do this in React

class Foo extends React.Component {
    constructor(props) {
        super(props)
    
        this.state = {
            result: undefined
        }
    }

    componentDidMount() {
        this.setState({result: await getResult()})
    }
}

In Flutter, the only way to know if the widget is mounted is checking the “mounted” property, this property is setted to true when this condition matches:

After creating a State object and before calling initState, the framework “mounts” the State object by associating it with a BuildContext. The State object remains mounted until the framework calls dispose, after which time the framework will never ask the State object to build again.

Flutter docs https://api.flutter.dev/flutter/widgets/State/mounted.html

If you need to do the typical “fetch on mount” pattern from React, you can use a FutureBuilder, or fetch from the initState method.

Render

In flutter, the render method is called build

In this method you should return your widget tree

React way:

class Foo extends React.Component {
    constructor(props) {
        super(props)
    
        this.state = {
            whatever: whateverValue    
        }        
    }


    render() {
        return <div>Your component stuff</div>
    }
    
}

Flutter life-cycle method. As in React, DON’T try to set the state here, it will create an endless loop.

class Foo extends StatelessWidget {
  const Foo({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text("Hi"),
    );
  }
}

ComponentDidUpdate

The Flutter life-cycle method equivalent to React componentDidUpdate is didChangeDependencies.

This method is called inmediately after initState, and is re-triggered every time one your state changes

React way:

class Foo extends React.Component {
    constructor(props) {
        super(props)
    
        this.state = {
            whatever: whateverValue    
        }        
    }

    componentDidUpdate(prevProps, prevState) {
        
        // Do your stuff here, you can check which dependency changed
    }
    
    render() {
        return <div>Your component stuff</div>
    }
    
}

Flutter way:

class Foo extends StatelessWidget {
  const Foo({Key key}) : super(key: key);

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // Do your stuff here like, like a network request
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text("Hi"),
    );
  }
}

ComponentWillUnmount

The flutter life-cycle method equivalent is the dispose method.

This method will set mounted to false, you should cancel all your listeners or subscriptions here.

React way:

class Foo extends React.Component {
    constructor(props) {
        super(props)
    
        this.state = {
            whatever: whateverValue    
        }        
    }

    componentWillUnmount() {
        // Cancel your listeners
    }
    
    
    
    render() {
        return <div>Your component stuff</div>
    }
    
}

Flutter way:

class Foo extends StatelessWidget {
  const Foo({Key key}) : super(key: key);

  @override
  void dispose() { 
    // Cancel your listeners, streams, subscriptions etc here
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text("Hi"),
    );
  }
}