reflex icon indicating copy to clipboard operation
reflex copied to clipboard

When rx.cond and rx.accordian are used together, the open accordian is closed when the `value` prop in accordion Item is not set after applying deltas.

Open Evenzel opened this issue 10 months ago β€’ 4 comments

Describe the bug When rx.cond and rx.accordian are used together, the open accordian is closed when rx.form is submitted.

To Reproduce


import reflex as rx


class TestState(rx.State):
    result: dict = {}

    def handle_submit(self, data):
        self.result = data


@rx.page(route="/")
def index():
    return rx.cond(
        TestState.is_hydrated,
        rx.vstack(
            rx.form(
                rx.vstack(
                    rx.accordion.root(
                        rx.accordion.item(
                            header='test',
                            content=rx.hstack(
                                rx.select(
                                    ["Yes", "No"],
                                    placeholder="Select an option",
                                    name="test_form",
                                    font_size="1em",
                                ),
                                rx.button("Submit", type_="submit"),
                            ),
                        ),
                        collapsible=True,
                    ),
                ),
                on_submit=TestState.handle_submit,
            ),
            rx.text(TestState.result['test_form'])
        ),
        rx.chakra.spinner(),
    )


app = rx.App()

Expected behavior accordian should not be closed.

Screenshots

  1. Before submit image

  2. After submit image

Specifics (please complete the following information):

  • Python Version: 3.11.4
  • Reflex Version: 0.4.7
  • OS: Windows 10
  • Browser (Optional): Chrome

Additional context Add any other context about the problem here.

Evenzel avatar Apr 14 '24 14:04 Evenzel

I've played around this a bit and I suspect this might be a radix bug(would need further investigations to conclude). For AccordionItem, we generate a random value for the value prop which is required by radix and is used in controlling the item based on the trigger. For some weird reason when state value changes (or deltas are applied after an event handler is triggered), the accordion item doesn't maintain its state(open/closed). This would require some further investigations into how radix treats the value prop since they don't seem to render the value prop in the DOM. But this behavior seems to show up when the accordion is in a conditional.

Even without the form, this is enough to repro:


import reflex as rx


class TestState(rx.State):
    val : bool = True
    num: int = 0

    def increment(self):
        self.num += 1


@rx.page(route="/")
def index():
    return rx.cond(
        TestState.val,
        rx.vstack(
            rx.text(TestState.num),
            rx.button("incremment", on_click=TestState.increment),
            rx.vstack(
                rx.accordion.root(
                    rx.accordion.item(
                        header='test',
                        content=rx.hstack(
                            rx.select(
                                ["Yes", "No"],
                                placeholder="Select an option",
                                name="test_form",
                                font_size="1em",
                            ),
                        ),
                    ),
                    collapsible=True,
                ),
            ),
        ),
        rx.chakra.spinner(),
    )

A workaround will be to provide a value for the accordion item:

...
rx.accordion.root(
    rx.accordion.item(
          header='test',
          content=rx.hstack(
                            rx.select(
                                ["Yes", "No"],
                                placeholder="Select an option",
                                name="test_form",
                                font_size="1em",
                            ),
                            rx.button("Submit", type_="submit"),
          ),
         value="item1" # provide a value 
   ),
  collapsible=True,
),

ElijahAhianyo avatar Apr 15 '24 14:04 ElijahAhianyo

A workaround will be to provide a value for the accordion item:

does this have to be a predefined state value or can it just be any old string, i ask because you defined value = "item1" but item1 was never mentioned anywhere in the provided snippet

Anga205 avatar Apr 19 '24 16:04 Anga205

A workaround will be to provide a value for the accordion item:

does this have to be a predefined state value or can it just be any old string, i ask because you defined value = "item1" but item1 was never mentioned anywhere in the provided snippet

Yes, value can be any arbitrary string

ElijahAhianyo avatar Apr 19 '24 16:04 ElijahAhianyo

Since the UUID is generated on the frontend rather than during compilation, state changes which trigger a re-render will generate a new UUID, so the currently open tabs don't match anymore.

Lendemor avatar May 03 '24 13:05 Lendemor