reflex icon indicating copy to clipboard operation
reflex copied to clipboard

[BUG] in the component part, object value is not converted to their value

Open matt-grain opened this issue 3 years ago β€’ 1 comments

As discussed on discord.

Little PoC:

"""Welcome to Pynecone! This file outlines the steps to create a basic app."""
from pcconfig import config

import pynecone as pc
from typing import List, Dict

docs_url = "https://pynecone.io/docs/getting-started/introduction"
filename = f"{config.app_name}/{config.app_name}.py"


class State(pc.State):
    """The app state."""

    button_state: Dict[int, str] = {}
    answers: List[str] = [ "test", "no test" ]
    value: str

    def set_value(self, answer: str) -> None:
        self.button_state[0] = answer
        print(f"{self.button_state[0]=}")


def c_button_icon(answer: str) -> pc.Component:

    return pc.hstack(
        pc.button(
            answer,
            size="lg",
            on_click=lambda: State.set_value(answer),
            is_active=State.button_state[0] == answer,  # THIS DOESN'T WORK
        ),
    )

def index():
    return pc.center(
        pc.vstack(
            pc.heading("Welcome to Pynecone Bugs!", font_size="2em"),
            pc.foreach(State.answers, lambda answer: c_button_icon(answer)),
            spacing="1.5em",
            font_size="2em",
        ),
        padding_top="10%",
    )


# Add state and page to the app.
app = pc.App(state=State)
app.add_page(index)
app.compile()

matt-grain avatar Jan 13 '23 22:01 matt-grain

Did some digging on this with @ElijahAhianyo on Discord, the cause seems to be due to StateUpdate not sending the correct delta for Var of type Dict

Here is the minimal example I used to find out:

class State(pc.State):
    button_state: Dict[int, str] = {}
    value: str = "value"

    def set_value(self, answer: str) -> None:
        self.button_state[0] = answer
        self.value = answer

def c_button(answ: str) -> pc.Component:
    return pc.hstack(
        # trigger
        pc.button(answ, on_click=lambda: State.set_value(answ)),
        # work
        pc.button(State.value, is_active=State.value == answ),
        # doesn't work
        pc.button(State.button_state[0], is_active=State.button_state[0] == answ),
    )

def index():
    return pc.center(pc.vstack(c_button("trigger")))

Steps:

  1. pc run & open the page
    image
  2. Click trigger
  3. 2nd button will update correctly, but 3rd button doesn't show anything image
  4. Refresh with F5, and 3rd button is now correct image

So it seems deltas are not being determined correctly, and not process the same way during an event vs page reload.

Lendemor avatar Jan 18 '23 20:01 Lendemor

This is related to the state mutation issue - if you add the extra line at the end:

self.button_state = self.button_state

it seems to work.

Once we have pc.dict implemented, we should be able to auto-detect mutations. I'll close this as a duplicate of that ticket.

picklelo avatar Jan 30 '23 18:01 picklelo