Skip to content

Commit 1980b17

Browse files
Add documentation for rx.memo decorator
Co-Authored-By: Alek Petuskey <alek@pynecone.io>
1 parent 436f2f4 commit 1980b17

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

docs/api-reference/memo.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
```python exec
2+
import reflex as rx
3+
4+
from pcweb.templates.docpage import docdemo, h1_comp, text_comp, docpage
5+
6+
def basic_example():
7+
@rx.memo
8+
def memoized_component(text_var: rx.Var[str]) -> rx.Component:
9+
return rx.text(text_var)
10+
11+
class MemoState(rx.State):
12+
count: int = 0
13+
text: str = "This component is memoized and won't re-render when the counter changes."
14+
15+
def increment(self):
16+
self.count += 1
17+
18+
return rx.vstack(
19+
rx.hstack(
20+
rx.button("Increment Counter", on_click=MemoState.increment),
21+
rx.text(f"Count: {MemoState.count}"),
22+
),
23+
memoized_component(MemoState.text),
24+
spacing="4",
25+
)
26+
27+
def recursive_example():
28+
class RecursiveState(rx.State):
29+
depth: int = 3
30+
31+
def increase_depth(self):
32+
self.depth += 1
33+
34+
def decrease_depth(self):
35+
if self.depth > 0:
36+
self.depth -= 1
37+
38+
@rx.memo
39+
def recursive_component(depth: rx.Var[int]) -> rx.Component:
40+
return rx.cond(
41+
depth <= 0,
42+
rx.text("Reached bottom!"),
43+
rx.vstack(
44+
rx.text(f"Depth: {depth}"),
45+
recursive_component(depth - 1),
46+
border="1px solid #eaeaea",
47+
padding="1em",
48+
border_radius="0.5em",
49+
)
50+
)
51+
52+
return rx.vstack(
53+
rx.hstack(
54+
rx.button("Increase Depth", on_click=RecursiveState.increase_depth),
55+
rx.button("Decrease Depth", on_click=RecursiveState.decrease_depth),
56+
),
57+
recursive_component(RecursiveState.depth),
58+
spacing="4",
59+
)
60+
61+
def event_handler_example():
62+
class EventState(rx.State):
63+
clicked: bool = False
64+
65+
def toggle(self):
66+
self.clicked = not self.clicked
67+
68+
@rx.memo
69+
def memoized_with_event(handler) -> rx.Component:
70+
return rx.button(
71+
"Click Me",
72+
on_click=handler,
73+
color=rx.cond(EventState.clicked, "green", "blue"),
74+
)
75+
76+
return rx.vstack(
77+
rx.text(f"Button clicked: {EventState.clicked}"),
78+
memoized_with_event(EventState.toggle),
79+
spacing="4",
80+
)
81+
```
82+
83+
# Memoization with rx.memo
84+
85+
The `rx.memo` decorator is used to memoize components in Reflex applications. Memoization is a performance optimization technique that prevents unnecessary re-renders of components when their inputs haven't changed.
86+
87+
## Basic Usage
88+
89+
Use the `@rx.memo` decorator on component functions to memoize them:
90+
91+
```python
92+
@rx.memo
93+
def my_component(text: rx.Var[str]) -> rx.Component:
94+
return rx.text(text)
95+
```
96+
97+
When a component is memoized, Reflex will only re-render it when its inputs (props) change. This can significantly improve performance in complex applications with many components.
98+
99+
```python eval
100+
basic_example()
101+
```
102+
103+
## Benefits of Memoization
104+
105+
- **Performance Optimization**: Prevents unnecessary re-renders when component props haven't changed
106+
- **Reduced Computation**: Avoids expensive calculations when inputs remain the same
107+
- **Smoother UI**: Helps maintain responsive user interfaces in complex applications
108+
109+
## Advanced Usage
110+
111+
### Recursive Components
112+
113+
The `rx.memo` decorator supports recursive UI elements, allowing you to create components that reference themselves:
114+
115+
```python eval
116+
recursive_example()
117+
```
118+
119+
### Components with Event Handlers
120+
121+
You can pass event handlers as arguments to memoized components:
122+
123+
```python eval
124+
event_handler_example()
125+
```
126+
127+
## When to Use Memoization
128+
129+
Memoization is most beneficial in the following scenarios:
130+
131+
1. **Complex Components**: When components perform expensive calculations or rendering
132+
2. **Deeply Nested Components**: When components are deep in the component tree and re-render frequently
133+
3. **Components with Stable Props**: When components receive props that rarely change
134+
135+
## Implementation Details
136+
137+
Under the hood, `rx.memo` works by:
138+
139+
1. Comparing the current props with previous props
140+
2. Skipping the re-render if all props are the same
141+
3. Re-rendering only when props have changed
142+
143+
This optimization helps maintain application performance as your Reflex app grows in complexity.

0 commit comments

Comments
 (0)