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) – Thefnwill be called to recompute the value when thedependenciesare not__eq__to the olddependencies. IfdependenciesisNone, 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.
Example use_memo#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
@componentwhich has a prop that is a function.This Hook can store callback function with specific bound
dependenciesand the callback function will only change when the specifieddependenciesare not__eq__to thedependenciesfrom 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_clickprop.This
SuperCompcomponent will re-render every time thefastpropprop 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
@componentto render the buttons. This newButtons100@componentwill only re-render when itsclick_handlerprop 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_handlerprop for theButtons100component is a new functionvalue_from_slowpropevery time that theSuperCompcomponent re-renders, so it will always cause theButtons100to re-render.We can’t define
value_from_slowpropas a constant function declared outside of theSuperCompcomponent because it depends on bindings toslowpropandvalue_set.Memoize a function definition: The solution#
So we use the
use_memo()Hook to create a callback function which only changes whenslowpropchanges.And now the
Buttons100will only re-render when theslowpropchanges.(The
value_setsetter function does not need to be in thedependenciesbecause 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
lambdafunction passed touse_memo()will only be called when theslowpropchanges, so the memoizedvalue_from_slowpropfunction will only change when theslowpropchanges.