Вызов javascript из Blazor приводит к ошибке

У меня есть приложение Blazor, построенное на.NET Core 3.1, и мне нужно иметь доступ к ресурсам USB-порта. Я получаю сообщение об ошибке:

В настоящее время вызовы взаимодействия JavaScript не могут быть выполнены. Это связано с тем, что компонент визуализируется статически. Когда предварительная отрисовка включена, вызовы взаимодействия JavaScript могут выполняться только во время метода жизненного цикла OnAfterRenderAsync.

У меня есть довольно простой компонент Blazor, обертывающий библиотеку Blazor.Extensions.WebUSB

public partial class Recordings : ComponentBase
{
    [Inject] private IUSB _usb { get; set; }
    [Inject] private ILogger<Recordings> _logger { get; set; }
    [Inject] private IJSRuntime _runtime { get; set; }

    private bool _initialized = false;


    protected override Task OnAfterRenderAsync(bool firstRender)
    {
        if (!_initialized)
        {
            this._usb.OnConnect += OnConnect;
            this._usb.OnDisconnect += OnDisconnect;
            this._usb.Initialize();
            this._initialized = true;
        }
        return Task.CompletedTask;

    }

    protected async Task GetDevices()
    {
        var devices = await this._usb.GetDevices();

        if (devices != null && devices.Length > 0)
        {
            _logger.LogInformation("Device list received");
        }
    }

    private void OnConnect(USBDevice device)
    {
        this._logger.LogInformation("Device connected");
    }

    private void OnDisconnect(USBDevice device)
    {
        this._logger.LogInformation("Device disconnected");
    }
}

И хотя я выполняю JS-взаимодействие в OnAfterRenderAsync, как было предложено, я все равно получаю ту же ошибку. Я попытался отложить вызов _usb.Initialize до тех пор, пока не будет нажата кнопка (это означает, что компонент определенно должен завершить рендеринг.

Я попытался отключить предварительную отрисовку, установив атрибут режима рендеринга в _Host.cshtml на Server вместо ServerPrerendered, но ничего не изменилось.

1 ответ

Ваш код должен быть таким:

 protected override Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        this._usb.OnConnect += OnConnect;
        this._usb.OnDisconnect += OnDisconnect;
        this._usb.Initialize();
        this._initialized = true;
    }
    return Task.CompletedTask;

}

Примечание. Когда переменная firstRender имеет значение true, что происходит только один раз, вы можете использовать JSInterop. До этого нельзя. Это подходящее время и место для инициализации ваших объектов JavaScript.

Методы жизненного цикла OnAfterRender(Boolean) и OnAfterRenderAsync(Boolean) полезны для выполнения взаимодействия или взаимодействия со значениями, полученными из @ref. Используйте параметр firstRender, чтобы гарантировать, что инициализация выполняется только один раз.

Надеюсь это поможет...

Другие вопросы по тегам