Search code examples
javascriptreactjsstenciljs

Why do StencilJS docs recommend making network calls in componentWillLoad?


I'm working on a Stencil JS project, that makes some network calls to get data and update state.

In React JS, a network call would be done in componentDidMount lifecycle method, and not in componentWillMount method.

I'm surprised to find almost the opposite recommendation in the Stencil docs:

componentWillLoad() Called once just after the component is first connected to the DOM. Since this method is only called once, it's a good place to load data asynchronously.

Stencil favors componentWillLoad over componentDidLoad in another case too. It logs out console warnings when using componentDidLoad to update state:

STENCIL: The state/prop "exampleProp" changed during "componentDidLoad()", this triggers extra re-renders, try to setup on "componentWillLoad()"

Why does Stencil push users to componentWillLoad method (before render), while React pushes users to componentDidMount method (after render)?


Solution

  • To start off I don't know much about React but I saw that componentWillMount was deprecated with the following explanation.

    There is a common misconception that fetching in componentWillMount lets you avoid the first empty rendering state. In practice this was never true because React has always executed render immediately after componentWillMount. If the data is not available by the time componentWillMount fires, the first render will still show a loading state regardless of where you initiate the fetch. This is why moving the fetch to componentDidMount has no perceptible effect in the vast majority of cases.

    In Stencil you can return a Promise in componentWillLoad which will prevent the component from rendering until that Promise has resolved (but I never found a practical use-case for this).

    If you don't return a Promise then depending on the speed of the your render method (any possibly other render lifecycle methods) componentDidLoad will run slightly later, which will probably be minimal most of the time (i.e. "no perceptible effect") but without any advantage (that I can think of).

    componentDidLoad is meant for things that have to run right after the first render.

    Similarly the console warning is because most of the time it doesn't make sense to synchronously modify a @State() or @Prop() property in componentDidLoad as it can often be easily moved to an earlier lifecycle method (avoiding a re-render just after the initial render). There are exceptions though, e.g. if the state value depends on the generated DOM, in that case you can ignore the warning.

    Note that in some cases connectedCallback might be even more appropriate than componentWillLoad e.g. the clock example in Stencil's Life Cycle Methods docs.