Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: cannot find a provider for current agent #3698

Open
3 tasks
FantasyPvP opened this issue Aug 1, 2024 · 2 comments
Open
3 tasks

Error: cannot find a provider for current agent #3698

FantasyPvP opened this issue Aug 1, 2024 · 2 comments
Labels

Comments

@FantasyPvP
Copy link

Problem
when trying to make a reactor agent i get the above error message after the code compiled successfully

Steps To Reproduce
Steps to reproduce the behavior:
All code and full error message attached below

Expected behavior
the code runs after compiling with no runtime errors

Screenshots
image

Environment:

  • Yew version: v0.21
  • Rust version: v1.82.0-nightly
  • Target, if relevant: wasm32-unknown-unknown
  • Build tool, if relevant: trunk
  • OS, if relevant: linux x86_64
  • Browser and version, if relevant: brave v1.67.119

Questionnaire

  • I'm interested in fixing this myself but don't know where to start
  • I would like to fix and I have a solution
  • I don't have time to fix this right now, but maybe later
use std::{borrow::Cow, sync::Arc};

use futures::{lock::Mutex, SinkExt, StreamExt};

use reqwasm::websocket::{futures::WebSocket, Message};
use serde::{Deserialize, Serialize};
use wasm_bindgen_futures::spawn_local;
use yew::{function_component, hook, html, use_effect_with, use_node_ref, use_state, use_state_eq, BaseComponent, Callback, Event, Html, Properties};
use yew_agent::{oneshot::OneshotProvider, prelude::use_oneshot_runner, reactor::{reactor, use_reactor_bridge, ReactorEvent, ReactorScope}};

use crate::components::{navbar::Navbar, button::Button};

#[derive(Properties, PartialEq, Default)]
pub struct ChatProps {
    messages: Vec<PublicMessage>
}

#[function_component(Chat)]
pub fn chat(props: &ChatProps) -> Html {

    let messages = Arc::new(use_state_eq(|| props.messages.clone() ));
    let messages_reactor = messages.clone();

    let reactor = use_reactor_bridge(move |output: ReactorEvent<ChatReactor>| match output {
        ReactorEvent::Output(msg) => {
            let mut msg_list: Vec<PublicMessage> = messages_reactor.to_vec();
            msg_list.push(msg);
            messages_reactor.set(msg_list);
        }
        _ => {}
    });

    let submit = Callback::from(move |_| {


        let _ = reactor.send(String::new());
    });

    html! {
        <>
            <Navbar user_id={ None }/>
            <div class="messenger-page-container">
                <div class="messenger-main-section" id="messages">
                    { 
                        messages.clone().iter().map(|m| {
                            html! {
                                <div class="message-container" id={ m.message_id.to_string() }>
                                <img class="message-avatar" src={ format!("/userassets/avatar/{}.png", m.user_id)}/> 
                                <div class="message-outer">
                                    <div class="message-inner">
                                        <div class="message-header">
                                            <div class="message-username">{ m.display_name.clone() }</div>
                                            <div class="message-date"> { m.created_at } </div>
                                        </div>
                                        <div class="message-body">{ m.content.clone() }</div>    
                                    </div>
                                </div>
                            </div>
                            }
                        }).collect::<Html>()
                    }
                </div>
                <div class="messenger-end-marker">{ "Already At Newest Messages" }</div>
            </div>
            <div class="messenger-entry-container" style="width: 100%; position: absolute; bottom: 0px; align-items: center; display: flex; flex-direction: column">
                <div class="messenger-main-section">
                    <div class="ui-horizontal-menu">
                        <img src="/static/icons/messenger.svg" style="padding: 0px 10px"/>
                        <input style="width: 100%;" class="ui-input" id="inputField" type="text" placeholder="Send Message"/>
                        <button class="ui-button" id="enterButton" onclick={ submit }>
                            <img src="/static/icons/return.svg"/>
                        </button>
                    </div>
                </div>        
            </div>
        </>
    }
}


#[reactor(ChatReactor)]
pub async fn chat_reactor(mut scope: ReactorScope<String, PublicMessage>) {
    let arcscope_rx = Arc::new(Mutex::new(scope));
    let arcscope_tx = Arc::clone(&arcscope_rx);
    let ws = WebSocket::open("ws://localhost:8000/messenger/connect/1").unwrap();
    let (mut ws_sender, mut ws_receiver) = ws.split();

    spawn_local(async move {
        while let Some(msg) = ws_receiver.next().await {
            match msg {
                Ok(Message::Text(data)) => {
                    log::debug!("{}", data);
                
                    let message: PublicMessage = serde_json::from_str(&data).unwrap();
                    arcscope_tx.lock().await.send(message).await.unwrap();

                }
                Ok(Message::Bytes(b)) => {
                    if let Ok(data) = String::from_utf8(b) {
                        log::debug!("{}", data);

                        let message: PublicMessage = serde_json::from_str(&data).unwrap();
                        arcscope_tx.lock().await.send(message).await.unwrap();
                    }
                },
                Err(e) => {
                    log::error!("{}", e);
                }
            }
        }
    });

    spawn_local(async move {
        while let Some(msg) = arcscope_rx.lock().await.next().await {
            if let Err(e) = ws_sender.send(Message::Text(serde_json::to_string(&msg).unwrap())).await {
                log::error!("{}", e);
            }
        }
        log::debug!("Websocket connection closed");
    });
}


#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
pub struct PublicMessage {
    pub message_id: i32,
    pub user_id: i32,
    pub display_name: String,
    pub created_at: i64,
    pub content: String,
}
@FantasyPvP FantasyPvP added the bug label Aug 1, 2024
@FantasyPvP
Copy link
Author

just to add to this. the exact point where the error seems to occur is when i create a reactor using the use_reactor_bridge method. removing all the logic from my actual reactor and simply setting a catch all case that does nothing

  let reactor = use_reactor_bridge(move |output: ReactorEvent<ChatReactor>| match output {
        _ => {}
    });

#[reactor(ChatReactor)]
pub async fn chat_reactor(mut scope: ReactorScope<String, PublicMessage>) {}

the above code still results in the same error

@AngelOnFira
Copy link

For posterity, I just came across a similar issue, and found the resolution.

On the Yew Discord, this discussion gave me the answer: link only works if you're on the Discord server

image

Where it refers to this code:

#[function_component]
pub fn App() -> Html {
    html! {
        <OneshotProvider<FibonacciTask, Postcard> path="/worker.js">
            <Main />
        </OneshotProvider<FibonacciTask, Postcard>>
    }
}

Basically, we need to wrap our applications in the providers. My code looks like this after the fix:

#[function_component(App)]
pub fn app() -> Html {
    html! {
        <ReactorProvider<WebSocketReactor> path="/services/game_service.js">
            <BrowserRouter>
                <Switch<Route> render={switch} />
            </BrowserRouter>
        </ReactorProvider<WebSocketReactor>>
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants