Itās no problem receiving events from the component but I canāt seem to round trip the processed event ānewValueā back to my component via my component_host reference.
Any ideas? Do I need to post ānextValueā to a REST endpoint hosted in my React component instead (and use global state like Redux to share that value between the endpoint and component)? This seems convoluted given I think I have a channel already in component_host.
Let me make sure Iām understanding the question:
event = component_host(key='id1', **props)
newValue = processEvent(event)
# You want to send newValue back to component_host?
Assuming this is the case, the answer is that it canāt be done particularly easily. You can effectively communicate āonceā with your component each time your script runs. (That is, you can invoke the component - which instantiates it, sends its parameters to the frontend, and retrieves the latest value returned from the frontend - once per run.)
If you want to do component_host(new_value), you could store new_value in a SessionState object, and retrieve it at the start of your app script. (And you can force your script to re-run by using the st.experimental_rerun API.)
But this is a bit awkward, and I wonder if thereās a better way to accomplish what youāre looking for. Can you describe your use case and data flow in more detail?
Thanks for a quick response. This is all about trying to overcome the allow-same-origin problem with components that need to make an API web request. What I ended up doing was getting the component to delegate the API web request back to Streamlit, and now I want to send those API results back to the component. Ultimately, what I want to do is integrate authentication with Auth0 identity provider, store API access tokens I receive in a remote DB and invoke APIs using said access tokens. Since components currently donāt allow API calls, Iām trying these workarounds.
I have an Auth0 login service (Flask App) integrated using an iframe in Streamlit. After the authentication callback completes, I display a code to the user who cuts and pastes it into the Streamlit app which makes a web request back to the Flask App to exchange the code for API access tokens (the Flask App maintains a DB of login codes and API access tokens for each user). Whilst this works, itās not seamlessā¦ hence all the jiggery pokery above.
Rather than solving it this way - which will continue to be painful, as it doesnāt mesh well with the Streamlit execution model - Iād suggest trying to move the auth step back up to the client (possibly with a proxy in between, if the Auth0 endpoint requires a non-null origin).
Components do allow API calls, but the allow-same-origin restriction definitely makes things trickier, because you need to make sure that CORS is properly configured at every link in the chain that returns a response to your componentās frontend.
The Flask example code I posted in the earlier question should work, for example. I tested it locally before posting it, just running with the simple flask dev server, via flask run --port 3001.
If youāre not able to get that example code to work, it might make more sense to begin with trying to debug that issue first. I wonder if the proxy you mentioned having set up is causing issues?
In my case, Streamlit is running on port 4008, the React component on port 3001, and the Flask API on port 8888. I have a proxy setting in Reactās package.json redirecting all unknown routes to 8888.
Is your component built and running under Streamlitās port? What if you set it up as I have?
My setup is identical to yours (Streamlit, component, Flask API all on different ports) - but Iām not using a node proxy. I can put together a sample, if itās useful.
@tim I hope I can save you some time, because I have managed to make it work following your guidance. In fact, I got both the session state + rerun approach (with my delegated web request to Streamlit) and direct api call schemes working. The latter is by far preferable!! I had unfortunately got { mode: āno-corsā } in my fetch header (in this post).
The rerun method is one time step behind the data that comes from the API call which is returned to the component to display, so wouldnāt be suitable. (I have a timestamp on it.)
I will post my solution as a gist ASAP. In the meantime, anyone reading this who wants it can send me a DM.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking āAccept allā, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.