edifice.use_memo#
- edifice.use_memo(fn, dependencies=())[source]#
Hook to memoize the result of calling a function.
Behaves like React useMemo.
- Parameters:
fn (
Callable
[[],TypeVar
(_T_use_memo
)]) – A function of no arguments which returns a value.dependencies (
Any
) – Thefn
will be called to recompute the value when thedependencies
are not__eq__
to the olddependencies
. Ifdependencies
isNone
, then the value will recompute on every render.
- Return type:
TypeVar
(_T_use_memo
)- Returns:
The memoized value from calling
fn
.
Memoize an expensive computation#
Use this Hook during a render to memoize a value which is pure and non-side-effecting but expensive to compute.
x_factor, x_factor_set = use_state(1) def expensive_computation(): return 1000000 * x_factor bignumber = use_memo(expensive_computation, (x_factor,))
Memoize a function definition#
This Hook also behaves like React useCallback.
Use this Hook to reduce the re-render frequency of a
@component
which has a prop that is a function.This Hook can store callback function with specific bound
dependencies
and the callback function will only change when the specifieddependencies
are not__eq__
to thedependencies
from the last render, so the callback function can be used as a stable prop which does not change on every render.Memoize a function definition: The problem#
We want to present the user with a hundred buttons and give the buttons an
on_click
prop.This
SuperComp
component will re-render every time thefastprop
prop changes, so then we will have to re-render all the buttons even though the buttons don’t depend on thefastprop
.@component def SuperComp(self, fastprop:int, slowprop:int): value, value_set = use_state(0) def value_from_slowprop(): value_set(slowprop) for i in range(100): Button(on_click=lambda _event: value_from_slowprop())
The general solution to this kind of performance problem is to create a new
@component
to render the buttons. This newButtons100
@component
will only re-render when itsclick_handler
prop changes.@component def Buttons100(self, click_handler:Callable[[], None]): for i in range(100): Button(on_click=lambda _event: click_handler()) @component def SuperComp(self, fastprop:int, slowprop:int): value, value_set = use_state(0) def value_from_slowprop(): value_set(slowprop) Buttons100(value_from_slowprop)
But there is a problem here, which is that the
click_handler
prop for theButtons100
component is a new functionvalue_from_slowprop
every time that theSuperComp
component re-renders, so it will always cause theButtons100
to re-render.We can’t define
value_from_slowprop
as a constant function declared outside of theSuperComp
component because it depends on bindings toslowprop
andvalue_set
.Memoize a function definition: The solution#
So we use the
use_memo()
Hook to create a callback function which only changes whenslowprop
changes.And now the
Buttons100
will only re-render when theslowprop
changes.(The
value_set
setter function does not need to be in thedependencies
because each setter function is constant, so it is always__eq__
from the previous render.)@component def Buttons100(self, click_handler:Callable[[], None]): for i in range(100): Button(on_click=lambda _event: click_handler()) @component def SuperComp(self, fastprop:int, slowprop:int): value, value_set = use_state(0) def value_from_slowprop(): value_set(slowprop) value_from_slowprop_memo = use_memo( lambda: value_from_slowprop, slowprop, ) Buttons100(value_from_slowprop_memo)
The
lambda
function passed touse_memo()
will only be called when theslowprop
changes, so the memoizedvalue_from_slowprop
function will only change when theslowprop
changes.