A record of the pitfalls of the WeChat applet component life cycle

A record of the pitfalls of the WeChat applet component life cycle

The component lifecycle is usually where our business logic begins.

If the business scenario is complex and the component life cycle does not perform as expected,

This may cause some weird business bugs that are extremely difficult to reproduce and fix.

Component attached Lifecycle execution times

According to common understanding, except for the life cycle of moved/show/hide, which may be executed multiple times,

Strictly speaking, the life cycle related to component loading, such as created, attached, ready, etc., should only be executed once for each component instance. But is this really the case?

background

The discovery of this problem comes from the error log of our mini program.

I received a lot of errors like Cannot redefine property: isComponent.

Cause Analysis

Through the variable name, we can trace back to the way we defined it in the code:

Component({
 lifetimes:
 attached() {
 Object.defineProperty(this, 'isComponent', {
 enumerable: true,
 get() { return true },
 });
 },
 },
});

It is easy to understand that the cause of this error is trying to redefine a non-configurable property of an object.

For details, please refer to the description on MDN.

But this definition is written in the attached lifecycle. Does it mean that the attached lifecycle of the component is triggered twice?

Oh my God, how is this possible?

Yes, it's that magical!

Scene restoration

This problem is not easy to reproduce, but by constantly simplifying and unraveling the problem, we finally found the root cause:

Before the page is onLoaded, the subcomponent rendering is triggered by changing the state through setData, and the attached lifecycle of the subcomponent will be triggered twice.

You can reproduce this scenario with the following code, or directly access the applet code snippet.

page

// page.js
Page({
 data: {
 showChild2: false,
 },
 onChild1Attached() {
 this.setData({ showChild2: true });
 },
});

<!-- page.wxml -->
<child1 bind:attached="onChild1Attached"></child1>
<child2 wx:if="{{ showChild2 }}"></child2>

Subcomponent 1

Rendered together with the page, and when attached, notified the page to update the status and render subcomponent 2 through triggerEvent.

//child1.js
Component({
 lifetimes:
 attached() {
 this.triggerEvent('attached');
 },
 },
});

<!-- child1.wxml -->
<view>child1</view>

Subcomponent 2

The attached lifecycle was executed twice, resulting in an error.

//child2.js
Component({
 lifetimes:
 attached() {
 Object.defineProperty(this, 'isComponent', {
 enumerable: true,
 get() { return true },
 });
 },
 },
});
<!-- child2.wxml -->
<view>child2</view>

Component ready life cycle execution time

The official documentation of the mini program does not clearly give the execution order of the component life cycle, but by printing the log we can easily find out:

  • During the loading phase, the following steps are executed in sequence: created -> attached -> ready
  • During the uninstallation phase, the following operations are executed in sequence:

So, it seems that the order should be: created -> attached -> ready -> detached.

But is this really the case?

background

For a period of time, customer service often reported that there was data stringing in our mini program.

For example: Merchant A’s live broadcast showcases Merchant B’s products.

Cause Analysis

String data occurs in multiple scenarios. Considering that the data is pushed to the mini program via messages, it is ultimately suspected that the problem lies in WebSocket communication.

On the mini program side, we encapsulate a WebSocket communication component, the core logic is as follows:

// socket.js
Component({
 lifetimes:
 ready() {
 this.getSocketConfig().then(config => {
 this.ws = wx.connectSocket(config);
 this.ws.onMessage(msg => {
 const data = JSON.parse(msg.data);
 this.onReceiveMessage(data);
 });
 });
 },
 detached() {
 this.ws && this.ws.close({});
 },
 },
 methods: {
 getSocketConfig() {
 // Request socket connection configuration from the server return new Promise(() => {});
 },
 onReceiveMessage(data) {
 event.emit('message', data);
 },
 },
});

Simply put, when the component is ready, a WebSocket connection is initialized and message push is listened, and then the connection is closed in the detached phase.

It seems that there is no problem, so we can only infer the situation that may not be in line with common sense from the results.

Data is out of order -> WebSocket message is out of order -> WebSocket is not closed properly -> close is wrong/detached is not executed/ready is executed after detached

Scene restoration

The actual business logic here is relatively complex, so it can only be verified through simplified code.

Through continuous experimentation, we finally found that:

There is no clear order in which components' ready and detached are executed.

You can reproduce this scenario with the following code, or directly access the applet code snippet.

page

// page.js
Page({
 data: {
 showChild: true,
 },
 onLoad() {
 this.setData({ showChild: false });
 },
});

<!-- page.wxml -->
<child wx:if="{{ showChild }}" />

Components

When a component is destroyed when it is not ready, detached will be executed synchronously first, and then ready will be executed asynchronously.

//child.js
Component({
 lifetimes:
 created() {
 console.log('created');
 },
 attached() {
 console.log('attached');
 },
 ready() {
 console.log('ready');
 },
 detached() {
 console.log('detached');
 }
 },
});

expand

Even if the initialization work is moved from the ready stage to the attached stage, as long as there is asynchronous operation, it is still possible that detached is executed before the asynchronous callback.

Therefore, please do not fully trust the destruction operation during the detached phase of the component.

Summarize

This is the end of this article about the pitfalls of WeChat Mini Program component life cycle. For more relevant content on the mini program component life cycle, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of the practical pitfalls of WeChat applet scroll-view horizontal scrolling and the implementation of hiding its scroll bar
  • WeChat applet uses npm support to step on the pit
  • Solutions to WeChat Mini Program Slot Pitfalls
  • WeChat applet pitfall record: solving the problem that the size of tabBar.list[3].selectedIconPath exceeds 40kb
  • The pitfall record of introducing vant-weapp into WeChat applet npm
  • WeChat applet custom tabBar stepping practice record
  • Echarts’s pitfalls in Taro WeChat applet development
  • Detailed explanation of the pitfalls of WeChat applet framework wepy (compared with vue)
  • WeChat applet development chapter: pitfall record

<<:  How to view the type of mounted file system in Linux

>>:  How to modify the password of MySQL 5.1 and remotely log in to the MySQL database

Recommend

MySQL 8.0.16 installation and configuration graphic tutorial under macOS

This article shares the installation and configur...

Bootstrap FileInput implements image upload function

This article example shares the specific code of ...

Key points for writing content of HTML web page META tags

The META tag is an auxiliary tag in the head area...

How to run Linux commands in the background

Normally, when you run a command in the terminal,...

Learn MySQL index pushdown in five minutes

Table of contents Preface What is index pushdown?...

HTML design pattern daily study notes

HTML Design Pattern Study Notes This week I mainl...

Vue echarts realizes horizontal bar chart

This article shares the specific code of vue echa...

Use CSS to create 3D photo wall effect

Use CSS to create a 3D photo wall. The specific c...

Docker installation and configuration steps for MySQL

Table of contents Preface environment Install Cre...

SQL query for users who have logged in for at least n consecutive days

Take 3 consecutive days as an example, using the ...

Hadoop 3.1.1 Fully Distributed Installation Guide under CentOS 6.8 (Recommended)

Foregoing: This document is based on the assumpti...

12 Laws of Web Design for Clean Code [Graphic]

Beautiful code is the foundation of a beautiful we...

Solution to Linux not supporting all commands

What should I do if Linux does not support all co...