Problems of replicating generated buildings

Background: To implement the build function in an Actor component, there is a building variable for the current preview, the purpose is to click on the preview to confirm the building to generate the building, the server-side operation is normal, but when the client clicks on the building, the building model will blink once and then normal.

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class CODEY_API UBuildComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	UBuildComponent();
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
	ABasePlayerController* GetBasePlayerController() const;
	FVector GetCursorLocation(ECollisionChannel CollisionChannel);

	void StartPreview(TSubclassOf<ABaseBuilding> BuildingClass);

	void StartBuild();
	
	UFUNCTION(Server, Reliable)
	void Server_StartBuild(TSubclassOf<ABaseBuilding> BuildingClass, FVector SpawnLocation);

	void CancelPreview();
	
	void PreviewFollowCursor();

protected:
	virtual void BeginPlay() override;
	
	UPROPERTY()
	ABaseBuilding* PreviewBuilding = nullptr;
};

UBuildComponent::UBuildComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
}

void UBuildComponent::BeginPlay()
{
	Super::BeginPlay();
}

void UBuildComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (PreviewBuilding)
	{
		PreviewBuilding->SetActorLocation(GetCursorLocation(ECC_LANDSCAPE));
	}
}


void UBuildComponent::StartPreview(TSubclassOf<ABaseBuilding> BuildingClass)
{
	if (!BuildingClass) return;

	GetBasePlayerController()->GetBaseASC()->AddLooseGameplayTag(FBaseGameplayTags::Get().Status_Build_PreviewBuild);

	const FVector SpawnLocation = GetCursorLocation(ECC_LANDSCAPE);

	FActorSpawnParameters SpawnParams;
	SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	PreviewBuilding = GetWorld()->SpawnActor<ABaseBuilding>(BuildingClass, SpawnLocation, FRotator::ZeroRotator,  SpawnParams);
	PreviewBuilding->SetReplicates(false);
	PreviewBuilding->SetActorEnableCollision(false);
	// TODO:设置预览材质
}

void UBuildComponent::StartBuild()
{
	if (PreviewBuilding)
	{
		if (GetOwnerRole() == ROLE_Authority || GetOwnerRole() == ROLE_AutonomousProxy)
		{
			const FVector SpawnLocation = GetCursorLocation(ECC_LANDSCAPE);
			Server_StartBuild(PreviewBuilding->GetClass(), SpawnLocation);
		}
	}
	CancelPreview();
}

void UBuildComponent::Server_StartBuild_Implementation(TSubclassOf<ABaseBuilding> BuildingClass, FVector SpawnLocation)
{
	if (BuildingClass)
	{
		FActorSpawnParameters ActorSpawnParameters;
		ActorSpawnParameters.Owner = GetBasePlayerController();
		ActorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

		ABaseBuilding* FinalBuilding = GetWorld()->SpawnActor<ABaseBuilding>(BuildingClass, SpawnLocation, FRotator::ZeroRotator, ActorSpawnParameters);
	}
}

void UBuildComponent::CancelPreview()
{
	if (PreviewBuilding)
	{
		PreviewBuilding->Destroy();
		PreviewBuilding = nullptr;
	}

	GetBasePlayerController()->GetBaseASC()->RemoveLooseGameplayTag(FBaseGameplayTags::Get().Status_Build_PreviewBuild);
}

void UBuildComponent::PreviewFollowCursor()
{
	if (PreviewBuilding)
	{
		PreviewBuilding->SetActorLocation(GetCursorLocation(ECC_Visibility));
	}
}

ABasePlayerController* UBuildComponent::GetBasePlayerController() const
{
	if (GetOwner())
	{
		return Cast<ABasePlayerController>(GetOwner());
	}
	return nullptr;
}

FVector UBuildComponent::GetCursorLocation(const ECollisionChannel CollisionChannel)
{
	return GetBasePlayerController()->GetCursorLocation(CollisionChannel);
}

Analysis: After the client clicks build, the server doesn’t generate the building immediately, but resets the client’s PreviewBuiling (at this time, Tick will find that the PreviewBuiling doesn’t exist and clear the client’s building), then the server generates the building and then synchronises it to the client, which leads to the flickering problem.

I thought about using RepNotify to sync the PreviewBuiling, but I don’t know how to do it.

Or is there any other way to do it, please advise!

OH, I can add a tag using AddLooseGameplayTag, but I can’t add a tag using AddReplicatedSubObject, I don’t know how to do it.