mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
⚡ Memoize static options in vertical-align* component
Wrap the radio-button options vector in `mf/with-memo []` so the vector allocation and `(tr ...)` calls happen once per component mount instead of on every render. Also document the translation memoization rule in frontend/AGENTS.md: `(tr ...)` must never be called at namespace level (locale is runtime-only), and static option lists should always be wrapped in `mf/with-memo []`. Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
parent
11c970a945
commit
6c19c7c0c4
@ -329,6 +329,31 @@ CSS modules pattern):
|
||||
- [ ] Selectors are flat (no deep nesting).
|
||||
|
||||
|
||||
### Translations (`tr`) and Memoization
|
||||
|
||||
`(tr "some.key")` resolves the translation string from the **currently active
|
||||
locale at call time**. This has two consequences:
|
||||
|
||||
- **Never call `(tr ...)` at namespace level** (inside a `def` or `defonce`).
|
||||
Doing so would freeze the label to the locale active at module load time and
|
||||
break runtime language switching.
|
||||
- **Always call `(tr ...)` at render time** — either directly in the component
|
||||
body or inside a `mf/with-memo` / `mf/use-memo` block.
|
||||
|
||||
When a component renders a **static list of options** whose labels come from
|
||||
`(tr ...)` (e.g. radio button options, select options), wrap the vector in
|
||||
`mf/with-memo []` with no dependencies. This ensures the vector and its
|
||||
`(tr ...)` calls are evaluated once per component mount instead of on every
|
||||
render, while still respecting the render-time requirement:
|
||||
|
||||
```clojure
|
||||
(let [options (mf/with-memo []
|
||||
[{:value "top" :label (tr "some.key.top")}
|
||||
{:value "center" :label (tr "some.key.center")}
|
||||
{:value "bottom" :label (tr "some.key.bottom")}])]
|
||||
...)
|
||||
```
|
||||
|
||||
### Performance Macros (`app.common.data.macros`)
|
||||
|
||||
Always prefer these macros over their `clojure.core` equivalents — they compile to faster JavaScript:
|
||||
|
||||
@ -102,6 +102,21 @@
|
||||
(mf/defc vertical-align*
|
||||
[{:keys [values on-change on-blur]}]
|
||||
(let [vertical-align (or (:vertical-align values) "top")
|
||||
options
|
||||
(mf/with-memo []
|
||||
[{:value "top"
|
||||
:id "vertical-text-align-top"
|
||||
:label (tr "workspace.options.text-options.align-top")
|
||||
:icon i/text-top}
|
||||
{:value "center"
|
||||
:id "vertical-text-align-center"
|
||||
:label (tr "workspace.options.text-options.align-middle")
|
||||
:icon i/text-middle}
|
||||
{:value "bottom"
|
||||
:id "vertical-text-align-bottom"
|
||||
:label (tr "workspace.options.text-options.align-bottom")
|
||||
:icon i/text-bottom}])
|
||||
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps on-change on-blur)
|
||||
@ -113,18 +128,7 @@
|
||||
[:> radio-buttons* {:selected vertical-align
|
||||
:on-change handle-change
|
||||
:name "vertical-align-text-options"
|
||||
:options [{:value "top"
|
||||
:id "vertical-text-align-top"
|
||||
:label (tr "workspace.options.text-options.align-top")
|
||||
:icon i/text-top}
|
||||
{:value "center"
|
||||
:id "vertical-text-align-center"
|
||||
:label (tr "workspace.options.text-options.align-middle")
|
||||
:icon i/text-middle}
|
||||
{:value "bottom"
|
||||
:id "vertical-text-align-bottom"
|
||||
:label (tr "workspace.options.text-options.align-bottom")
|
||||
:icon i/text-bottom}]}]]))
|
||||
:options options}]]))
|
||||
|
||||
(mf/defc grow-options*
|
||||
[{:keys [ids values on-blur]}]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user