Closed jsimonrichard closed 2 months ago
Things that call the inputPadding
function will ultimately get called again when isDisplayed
is toggled BUT that doesn't mean the leftContainer()!.offsetWidth
has resized yet. In fact, your example shows it hasn't - and since offsetWidth
isn't a reactive property it won't trigger an update when it does resize.
The console logged effect runs later, after the rendering updates, so it just so happens that offsetWidth
has changed by that time.
You may have more luck using resizeObserver
to watch the size of leftContainer
instead. There is a solid-primitive that might help you with that.
EDIT: Oh and regarding the createMemo
part of your question. That will also only rerun when isDisplayed
toggles - and it will be remembering the 0px measurement and returning that when the effect asks for it later. It too doesn't know that offsetWidth
has changed in the meantime.
Ah, I see now. Thanks for the detailed explanation!
Using createResizeObserver
from solid-primitive works great. For anyone else looking at this later, my solution looks something like this:
const [leftContainer, setLeftContainer] = createSignal();
const [leftWidth, setLeftWidth] = createSignal();
createEffect(() => {
if (!isDisplayed() || !leftContainer()) {
setLeftWidth(undefined);
return;
}
createResizeObserver(
leftContainer(),
({ width }) => {
setLeftWidth(width + 'px');
},
{ box: 'border-box' },
);
});
Describe the bug
I am trying to create an input that dynamically changes its padding based on the element included to the left of the input text (kind of like this component, but dynamic: https://tailwindui.com/components/application-ui/forms/input-groups#component-2607d970262ada86428f063c72b1e7bd). However, sometimes this element isn't displayed (
display: none
), which means I can't just calculate the size on mount usingoffsetWidth
.I was able to create a derived ref that calculates the correct size when the display mode is controlled by another signal (note the log statements in the effect in the MRE). However, if this is wrapped in a memo, the reported value changes. I'm probably doing something wrong here, but I'm opening this as an issue because I would not expect memoizing a value to change that value. In addition, that memoized value reflects what's actually used in the DOM regardless of whether the value specified in the JSX is memoized (in the MRE, I'm not actually using the memoized value in the JSX, but I'm still getting
0px
).I hope this MRE is sufficient. I would have liked to make it more minimal, but I really don't know what is essential here.
Your Example Website or App
https://stackblitz.com/edit/solidjs-templates-jmnrua?file=src%2FApp.tsx
Steps to Reproduce the Bug or Issue
inputPadding
andinputPaddingMemoized
Expected behavior
As a user, I expect derived signals and memos to behave the same when only used once in reactive context. In addition, I expect the value of a derived signal inside an effect to be the same as the value of that same signal when used in JSX.
Screenshots or Videos
No response
Platform
Additional context
No response