← SEARCHABLE ARCHIVE
Unreal Engine · 2026-07-04

Widget life cycle and delegate overlap connection

Issues that occur when NativeConstruct is called again

INTERACTIVE READING MODE →

The articles written on this blog were created with the goal of teaching. Also, the information in the article may be incorrect, so please be careful.

UUserWidget::NativeConstruct()It is easy to think that is called only once, when an object is first created. However, if the widget is removed from the screen and added again, Construct may be called again.

Delegate may be connected redundantly

void UDailyProblemWidget::NativeConstruct()
{
    Super::NativeConstruct();

    SubmitButton->OnClicked.AddDynamic(
        this,
        &UDailyProblemWidget::HandleSubmit
    );
}

If Construct is called twice, the function may be executed twice on the same button click. In the case of logic such as storage, goods deduction, and node creation, the actual data is processed redundantly.

In ProjectDT, it was organized to remove the same delegate before connecting.

if (SubmitButton)
{
    SubmitButton->OnClicked.RemoveDynamic(
        this,
        &UDailyProblemWidget::HandleSubmit
    );

    SubmitButton->OnClicked.AddDynamic(
        this,
        &UDailyProblemWidget::HandleSubmit
    );
}

NativeOnInitialized and NativeConstruct

A task that only needs to be prepared onceNativeOnInitialized()may be more suitable. The value that needs to be updated every time the screen comes back isNativeConstruct()I process it in a separate Setup function.

NativeOnInitialized: Once during the lifetime of the object
NativeConstruct: Can be called again when attached to a View
NativeDestruct: Called when leaving View

In a widget pooling or reuse structure, object creation and screen display should not be viewed as the same event. It is important to distinguish at what point each button connection, data initialization, and screen update should be performed.