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

rx.input rendered value its not same as state value #4629

Open
msiwik-epruf opened this issue Jan 13, 2025 · 5 comments
Open

rx.input rendered value its not same as state value #4629

msiwik-epruf opened this issue Jan 13, 2025 · 5 comments

Comments

@msiwik-epruf
Copy link

Describe the bug
After app start. When for example I change value of a, b or c. events is triggerred succesfully and for example if I change b -> 10 i see log From: b {'a': '1', 'b': '10', 'c': '11'} and on fronted a = 1, b = 10 and c = 11. But now if I Try to update variable with was updated before (like c from 5 to 11) then log of state is right From: c {'a': '5', 'b': '10', 'c': '15'} but on fronted nothing change (a=1, b=10 and c = 11). Now i can try to change any of values and nothing happens on fronted but state in logs updated everytime. If I manually refresh page in browser then values on fronted are now synced with state values

To Reproduce
Steps to reproduce the behavior:

  • Code/Link to Repo:
import reflex as rx


class MathState(rx.State):
    a: str = '1'
    b: str = '4'
    c: str = '5'
    
    def _log(self, _from: str = ''):
        data = {
            "a": self.a,
            "b": self.b,
            "c": self.c,
        }
        print("From: ", _from, data)
    
    
    @rx.event
    def update_a(self, a: str):
        self.a = a
        self.c = str(int(self.a) + int(self.b))
        self._log('a')
        
    @rx.event
    def update_b(self, b: str):
        self.b = b
        self.c = str(int(self.a) + int(self.b))
        self._log('b')
        
    @rx.event
    def update_c(self, c: str):
        self.c = c
        self.a = str(int(self.c) - int(self.b))
        self._log('c')



def index_abc():
    
    a_component = rx.vstack(rx.heading("a", size='4'), rx.input(default_value=MathState.a, name="a", on_blur=MathState.update_a))
    b_component = rx.vstack(rx.heading("b", size='4'), rx.input(default_value=MathState.b, name="b", on_blur=MathState.update_b))
    c_component = rx.vstack(rx.heading("c", size='4'), rx.input(default_value=MathState.c, name="c", on_blur=MathState.update_c))
    
    return rx.hstack(
        a_component,
        b_component,
        c_component,
    )


app = rx.App(
    theme=rx.theme(
        appearance="light", has_background=True, radius="large", accent_color="blue"
    ),
)

app.add_page(
    index_abc,
    title="Abc app",
    description="abc",
    route="/abc",
)

Expected behavior

Changing any values should alter both state on backend and values of fronted without manually refreshing brower page

Specifics (please complete the following information):

  • Python Version:
    Python 3.11.1
  • Reflex Version:
    reflex==0.6.8
    reflex-chakra==0.6.2
    reflex-hosting-cli==0.1.32
  • OS: MacOS 13.6.7 (22G720)
  • Browser (Optional):
    Chrome 131.0.6778.86 (Oficjalna wersja) (arm64)
Copy link

linear bot commented Jan 13, 2025

@masenf
Copy link
Collaborator

masenf commented Jan 13, 2025

The state vars in your example are bound to default_value, which means they are set when the component is mounted/initialized. If the values subsequently change after the page loads, you wouldn't see the update reflected in the frontend because the default has already been applied.

To work around this, you can set key=MathState.a (etc). This will cause the control to re-mount when the key var changes, and remounting the component will re-apply the default.

@msiwik-epruf
Copy link
Author

msiwik-epruf commented Jan 13, 2025

@masenf Can you explain how to use key? Becausue chaning default_value to key, or having them both on MathState.a and etc does not work.

@msiwik-epruf
Copy link
Author

Changing on blur to on change and. adding debounce got me expected behavior

a_component = rx.vstack(rx.heading("a", size='4'), rx.input(id='aid', value=MathState.a, name="a", on_change=MathState.update_a.debounce(300)))
b_component = rx.vstack(rx.heading("b", size='4'), rx.input(id='bid', value=MathState.b, name="b", on_change=MathState.update_b.debounce(300)))
c_component = rx.vstack(rx.heading("c", size='4'), rx.input(id='cid', value=MathState.c, name="c", on_change=MathState.update_c.debounce(300)))

@nagasatyadheerajanumala
Copy link

nagasatyadheerajanumala commented Jan 15, 2025

This issue is likely caused by the way Reflex is handling state synchronization between the backend and frontend. When the state updates, the frontend is not receiving or reacting to the changes as expected. Below is a modified version of your code that ensures the state updates properly reflect on the frontend.

import reflex as rx


class MathState(rx.State):
    a: str = rx.var('1')
    b: str = rx.var('4')
    c: str = rx.var('5')
    
    def _log(self, _from: str = ''):
        data = {
            "a": self.a,
            "b": self.b,
            "c": self.c,
        }
        print("From: ", _from, data)
    
    @rx.event
    def update_a(self, a: str):
        self.a = a
        self.c = str(int(self.a) + int(self.b))
        self._log('a')
        
    @rx.event
    def update_b(self, b: str):
        self.b = b
        self.c = str(int(self.a) + int(self.b))
        self._log('b')
        
    @rx.event
    def update_c(self, c: str):
        self.c = c
        self.a = str(int(self.c) - int(self.b))
        self._log('c')


def index_abc():
    a_component = rx.vstack(
        rx.heading("a", size='4'), 
        rx.input(default_value=MathState.a, name="a", value=MathState.a, on_change=MathState.update_a)
    )
    b_component = rx.vstack(
        rx.heading("b", size='4'), 
        rx.input(default_value=MathState.b, name="b", value=MathState.b, on_change=MathState.update_b)
    )
    c_component = rx.vstack(
        rx.heading("c", size='4'), 
        rx.input(default_value=MathState.c, name="c", value=MathState.c, on_change=MathState.update_c)
    )
    
    return rx.hstack(
        a_component,
        b_component,
        c_component,
    )


app = rx.App(
    theme=rx.theme(
        appearance="light", has_background=True, radius="large", accent_color="blue"
    ),
)

app.add_page(
    index_abc,
    title="Abc app",
    description="abc",
    route="/abc",
)

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

No branches or pull requests

3 participants