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(value=State.nested.var) is not updated when nested is set to a new object containing the same content. #3653

Open
abulvenz opened this issue Jul 10, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@abulvenz
Copy link
Contributor

Describe the bug
We have some validation checks in setters that do not let through some changes from the frontend. Unfortunately the reload button does not reset the UI.

To Reproduce
Steps to reproduce the behavior:

  • Use below app
  • Type an "a" into the input
  • Because your input is invalid, the state is not updated in the setter.
  • Click "Create new Object". This will overwrite the object in the state. # Here I would expect an update in the input.
  • The input still shows the old value, containing the "a".
  • Click "Create other Object". This time the input changes to "12345"
import reflex as rx

class Object(rx.Base):
    name: str = "1234"


class State(rx.State):
    """The app state."""
    message: str = "Default"
    object: Object = Object()

    def create_new_object(self):
        self.object = Object()
        self.message = self.object.name
        print(self.object.name)
    
    def create_new_object_2(self):
        self.object = Object(name="12345")
        self.message = self.object.name
        print(self.object.name)

    def set_name(self, value: str):
        if not "a" in value:
            self.object.name = value
            self.message = ""
        else:
            self.message="You can't use the letter 'a' in the name"

def index() -> rx.Component:
    return rx.container(
        rx.text(f"Your message: ", State.message), 
        rx.text(f"Object name: ", State.object.name),
        rx.input(value=State.object.name, on_change=State.set_name),
        rx.button("Create new object", on_click=State.create_new_object),
        rx.button("Create other object", on_click=State.create_new_object_2),
    )

app = rx.App()
app.add_page(index)

Expected behavior
The input should show the variable value after pressing the button.

@abulvenz abulvenz added the bug Something isn't working label Jul 10, 2024
@masenf
Copy link
Collaborator

masenf commented Jul 10, 2024

I believe the issue is nkbt/react-debounce-input#130

The internal state of the debounce is not getting updated because the bound state var does not actually change value [1].

I'm not sure if there's actually a fix we can make here 😔, but there are some potential workarounds:

  • set key prop on the rx.input to some value in the state that you increment/update when the object updates. This will force the input to be re-rendered with the correct value showing... Note however, reflex 0.5.6 currently has a bug where key is not passed through, so this would also need to be fixed in the framework before it's a real solution
  • trigger a state update in self.object.name to a different value, then set it back to the original value in the set_name function. The problem here is that the user gets their input swiped out from under them and reset to the last "valid" value, which is not a great UX.
  • in the create_new_object handler, if the new object name matches the current object name, first yield a state update that blanks out the self.object.name field, then update self.object to the new object. This is probably the cleanest workaround, but if these objects are getting created and assigned in multiple places, it's kind of a hassle, so you might need a helper function to handle the logic.

masenf added a commit that referenced this issue Jul 10, 2024
These fields on the base Component were not being carried onto the
DebounceInput component (to be passed to the child).

Discovered while testing #3653
@abulvenz
Copy link
Contributor Author

Thanks for the fast reply @masenf .
We have implemented the last workaround and yield the entire object as None and yield the new value afterwards. It causes a tiny flicker depending on the state size, but at least it works now as expected.

@benedikt-bartscher
Copy link
Contributor

We could try https://github.com/xnimorz/use-debounce which seems to be better maintained

masenf added a commit that referenced this issue Jul 12, 2024
These fields on the base Component were not being carried onto the
DebounceInput component (to be passed to the child).

Discovered while testing #3653
Alek99 pushed a commit that referenced this issue Jul 15, 2024
These fields on the base Component were not being carried onto the
DebounceInput component (to be passed to the child).

Discovered while testing #3653
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants