Add Conditional refs
Describe the bug
Conditional refs within a <For> block do not work as expected:
<For each={[1, 2]}>
{(num: number) => (
<div
ref={num === 1 ? oneRef : twoRef}
onClick={() =>
num === 1 ? console.log(oneRef) : console.log(twoRef)
}
>
number: {num}
</div>
)}
</For>
In the above snippet, the refs do not actually get applied to the either element.
Your Example Website or App
https://playground.solidjs.com/?hash=-912917438&version=1.4.3
Steps to Reproduce the Bug or Issue
- This issue can be better observed in this playground example one.
- Observe that logging either refs to console (from both
createEffectandonClick) returnundefined. - Observe also that the work-around (which is to forgo the use of the
<For>block) which is commented out in the above example returns the expected behaviour (logs the refs to console correctly). - What also works is non-conditional usage of refs as seen in playground example two.
- In this case, the ref will be passed to the second element only and returns it when logged to console.
Expected behavior
As a user, I expected refs to be passed to both elements conditionally (as confirmed by logging it to console) but neither elements received the refs (as seen when logging the refs to console returns undefined)
Screenshots or Videos
No response
Platform
- OS: macOS
- Browser: Chrome, Firefox, Safari
- Version: Chrome v104, Firefox v104, Safari v15.0
Additional context
No response
Hmm.. interesting. This has nothing to do with <For> We've never supported conditional refs. Didn't really think of them as a thing because they never update but I suppose structurally that could be a case. Not a bad feature request.
You can still use member access refs[cond ? 'prop1' : 'prop2'] instead plain variable to mimic conditional refs.
@mdynnl You mean putting the refs into an object or array and conditionally accessing them right? I just tried that and I don't think it works. Regular non-conditional access (refs.prop1) doesn't work as well.
https://playground.solidjs.com/?hash=1968952564&version=1.4.3 same should work for array
@mdynnl Indeed that works, thanks a lot!
@vxncetxn It works if you specify ref as a function:
ref={(el) => (num === 1 ? (oneRef = el) : (twoRef = el))}
https://playground.solidjs.com/?hash=1401208615&version=1.4.3
If you don't need the reactivity of the For component, would it be bad style to do const divs = [1, 2].map((i) => <div/>), then do whatever you plan to do with the refs directly on divs (if you only need onClick, I think you could work with e.target as well) and then return divs?
This requires more discussion/design. Welcome anyone to do so over in discussions.