diff --git a/pynecone/.templates/web/utils/state.js b/pynecone/.templates/web/utils/state.js index 6878bbe6c..ee58fa269 100644 --- a/pynecone/.templates/web/utils/state.js +++ b/pynecone/.templates/web/utils/state.js @@ -246,3 +246,13 @@ export const uploadFiles = async ( export const E = (name, payload) => { return { name, payload }; }; + + +/*** + * Check if a value is truthy in python. + * @param val The value to check. + * @returns True if the value is truthy, false otherwise. + */ +export const isTrue = (val) => { + return Array.isArray(val) ? val.length > 0 : !!val +} diff --git a/pynecone/compiler/compiler.py b/pynecone/compiler/compiler.py index d16b0801c..a35f4dab1 100644 --- a/pynecone/compiler/compiler.py +++ b/pynecone/compiler/compiler.py @@ -16,7 +16,13 @@ from pynecone.utils import imports, path_ops DEFAULT_IMPORTS: imports.ImportDict = { "react": {"useEffect", "useRef", "useState"}, "next/router": {"useRouter"}, - f"/{constants.STATE_PATH}": {"connect", "updateState", "uploadFiles", "E"}, + f"/{constants.STATE_PATH}": { + "connect", + "updateState", + "uploadFiles", + "E", + "isTrue", + }, "": {"focus-visible/dist/focus-visible"}, "@chakra-ui/react": {constants.USE_COLOR_MODE}, } @@ -86,7 +92,7 @@ def _compile_components(components: Set[CustomComponent]) -> str: """ imports = { "react": {"memo"}, - f"/{constants.STATE_PATH}": {"E"}, + f"/{constants.STATE_PATH}": {"E", "isTrue"}, } component_defs = [] diff --git a/pynecone/utils/format.py b/pynecone/utils/format.py index aed3d25eb..ab6ccddac 100644 --- a/pynecone/utils/format.py +++ b/pynecone/utils/format.py @@ -218,6 +218,9 @@ def format_cond( # Import here to avoid circular imports. from pynecone.var import Var + # Use Python truthiness. + cond = f"isTrue({cond})" + # Format prop conds. if is_prop: prop1 = Var.create(true_value, is_string=type(true_value) == str) diff --git a/tests/components/layout/test_cond.py b/tests/components/layout/test_cond.py index 6bc0fa230..a16b6ab02 100644 --- a/tests/components/layout/test_cond.py +++ b/tests/components/layout/test_cond.py @@ -40,7 +40,7 @@ def test_validate_cond(cond_state: pc.Var): ) assert str(cond_component) == ( - "{cond_state.value ? " + "{isTrue(cond_state.value) ? " "{`cond is True`} : " "{`cond is False`}}" ) @@ -71,7 +71,7 @@ def test_prop_cond(c1: Any, c2: Any): assert isinstance(prop_cond, Var) c1 = json.dumps(c1).replace('"', "`") c2 = json.dumps(c2).replace('"', "`") - assert str(prop_cond) == f"{{true ? {c1} : {c2}}}" + assert str(prop_cond) == f"{{isTrue(true) ? {c1} : {c2}}}" def test_cond_no_else(): diff --git a/tests/components/test_tag.py b/tests/components/test_tag.py index 417121959..99312cc49 100644 --- a/tests/components/test_tag.py +++ b/tests/components/test_tag.py @@ -163,4 +163,7 @@ def test_format_cond_tag(): false_value=str(Tag(name="h2", contents="False content")), cond=BaseVar(name="logged_in", type_=bool), ) - assert str(tag) == "{logged_in ?

True content

:

False content

}" + assert ( + str(tag) + == "{isTrue(logged_in) ?

True content

:

False content

}" + ) diff --git a/tests/test_utils.py b/tests/test_utils.py index 58630cc39..e24f5fb2f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -163,8 +163,8 @@ def test_indent(text: str, indent_level: int, expected: str, windows_platform: b @pytest.mark.parametrize( "condition,true_value,false_value,expected", [ - ("cond", "", '""', '{cond ? : ""}'), - ("cond", "", "", "{cond ? : }"), + ("cond", "", '""', '{isTrue(cond) ? : ""}'), + ("cond", "", "", "{isTrue(cond) ? : }"), ], ) def test_format_cond(condition: str, true_value: str, false_value: str, expected: str):