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.
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.