Rx.foreach and rx.cond with mixed var types?

I’m trying to render a list of elements that could be either type A or B.

Something like:


class A(rx.Base):
    a: str

Class B(rx.Base):
    b: int

class State(rx.State):
    mixed_list: list[A, B] = [A('a'), B(1), A('a2'), B(2)]

def render_a(obj: A) -> rx.Component:
    return rx.text(f'show A: {obj.a}')

def render_b(obj: B) -> rx.Component:
    return rx.text(f'show B: {obj.b}')

def render_a_or_b(obj: A | B) -> rx.Component:
    return rx.cond(is_a(obj), render_a(obj), render_b(obj))

def render_mixed_list(mixed: list[A | B]) -> rx.Component:
    return rx.foreach(State.mixed_list, render_a_or_b)

This is a very contrived example, but illustrates the problems:

  1. the is_a function… I’m not sure how I can actually check what type a Var is (maybe I can’t).
  2. Annotating with A | B causes problems inferring types (understandably…)

For now, my solution is to use something like this (adding to/modifying above):

class AorB(rx.Base):
    a_inst: A = None
    b_inst: B = None
    type_: str  # Either "A" or "B"

class State(rx.State):
    mixed_list: list[AorB] = [
        AorB(a_inst=A('a'), type_="A"), 
        AorB(b_inst=B(1), type_="B"), 
        ...
    ]

def render_a_or_b(obj: AorB) -> rx.Component:
    return rx.match(
        obj.type_, 
        ("A", render_a(obj.a_inst)), 
        ("B", render_b(obj.b_inst)), 
        rx.text(f"Wrong type {obj.type_}")
    )

Have I missed a cleaner solution, or would this be the way to go?

That’s generally the right approach.

The code sample that I posted last week shows a nice way of encapsulating this logic Rendering different content based on a discriminator field

Thanks for linking that. That answers my question exactly.