Before the user has interacted with the component, or while it is still rendering, the function _component_func
—returned by declare_component
—accepts a special default
argument to specify the initial return value of the component.
We can’t access the default
Python argument in the props of our component on the React side, though, so we will define an initialValue
argument to st_custom_component
. We then copy this argument in two places:
default
parameter for the _component_func
— this results in a value being assigned the first time the script runs; and,initialValue
argument, which is accessible in our React component.Start on the Python side, in the __init__.py
file :
import streamlit.components.v1 as components
_component_func = components.declare_component(
"custom_slider",
url="http://localhost:3001",
)
# Define a value argument in the wrapper function, pass it into `initialValue`
def st_custom_slider(label: str, min_value: int, max_value: int, value: int = 0, key=None):
component_value = _component_func(label=label, minValue=min_value, maxValue=max_value, initialValue=value, key=key, default=value)
return component_value
In app.py
:
import streamlit as st
from streamlit_custom_slider import st_custom_slider
# Pass an initial value to the Streamlit native slider
v = st.slider("Hello world", 0, 100, 50)
st.write(v)
# Pass an initial value to your custom slider
v_custom = st_custom_slider('Hello world', 0, 100, 50, key="slider1")
st.write(v_custom)
Then edit the CustomSlider.tsx
file to initialize the component’s state with the default value:
import React, { useEffect, useState } from "react";
import {
ComponentProps,
Streamlit,
withStreamlitConnection,
} from "streamlit-component-lib";
import { Slider } from "baseui/slider";
const CustomSlider = (props: ComponentProps) => {
// Get initialValue from props
const { label, minValue, maxValue, initialValue } = props.args;
// Set initial value of state using the initialValue prop
// This sets state each time the component is mounted
// so don't forget the key argument on the Python side to not remount every time !
const [value, setValue] = useState([initialValue]);
useEffect(() => Streamlit.setFrameHeight());
return (
<>
<h3>{label}</h3>
<Slider
value={value}
onChange={({ value }) => value && setValue(value)}
onFinalChange={({ value }) => Streamlit.setComponentValue(value)}
min={minValue}
max={maxValue}
/>
</>
);
};
export default withStreamlitConnection(CustomSlider);
At this stage, we are essentially imitating the native Streamlit API slider.