metal.js
metal.js copied to clipboard
Unexpected behavior on `defaultFn` with `replaceNonInternal`
When replaceNonInternal
is called on components that have non internal properties with computed defaults, those properties are re-computed.
Test case
Given this component:
// MyButton.es.js
import templates from './MyButton.soy';
export default class MyButton extends Component {
static STATE = {
label: {
value: ''
},
guid: {
valueFn: () => _.uniqueId('button')
}
}
}
Soy.register(MyButton, templates);
// MyButton.soy
{namespace MyButton}
/**
* @param guid
* @param label
*/
{template .render}
<button>{$guid} — {$label}</button>
{/template}
Used as such:
// MyApp.soy
{foreach $name in $names}
{call MyButton.render}
{param label: $name /}
{/call}
{/foreach}
Now if MyApp re-renders (you add a name
in $names
) you’ll see the problem in action.
Expected result
Every button keeps the guid it generated.
Actual result
Every re-render computes a new guid for each button component instance.
A very pratical solution would be to memoize defaultFn
functions per-instance at creation.
Potentially inefficient.