S
SolidJS4mo ago
Paul

How to get feedback from reactivity ?

Hey all I have the following component:
import { Button, Input, NumberInput, Stack } from "@mantine/core";
import { createSignal } from "solid-js";

export default function StoryComponent() {
const [value, setValue] = createSignal<number | string>('133');

return (
<div style={{ 'padding': '40px' }}>
<Stack>
<NumberInput
value={value()}
label="Number input"
placeholder="Number input"
onChange={setValue}
onValueChange={console.log}
/>
{typeof value() === 'number' ? `${value()} number` : `${value() === '' ? 'empty' : value()} string`}
<Button onClick={() => setValue(245.32)}>Set value to float</Button>
<Input
placeholder="Clearable input"
value={value()}
onChange={(event) => setValue(event.currentTarget.value)}
rightSection={value() !== '' ? <Input.ClearButton onClick={() => setValue('')} /> : undefined}
rightSectionPointerEvents="auto"
size="sm"
/>
</Stack>
</div>
);
}
import { Button, Input, NumberInput, Stack } from "@mantine/core";
import { createSignal } from "solid-js";

export default function StoryComponent() {
const [value, setValue] = createSignal<number | string>('133');

return (
<div style={{ 'padding': '40px' }}>
<Stack>
<NumberInput
value={value()}
label="Number input"
placeholder="Number input"
onChange={setValue}
onValueChange={console.log}
/>
{typeof value() === 'number' ? `${value()} number` : `${value() === '' ? 'empty' : value()} string`}
<Button onClick={() => setValue(245.32)}>Set value to float</Button>
<Input
placeholder="Clearable input"
value={value()}
onChange={(event) => setValue(event.currentTarget.value)}
rightSection={value() !== '' ? <Input.ClearButton onClick={() => setValue('')} /> : undefined}
rightSectionPointerEvents="auto"
size="sm"
/>
</Stack>
</div>
);
}
See video for it in action. It uses: NumberInput: https://raw.githubusercontent.com/paulm17/mantinesolid/refs/heads/main/packages/%40mantine/core/src/component/NumberInput/NumberInput.tsx NumberInput then passes it's value to InputBase: https://raw.githubusercontent.com/paulm17/mantinesolid/refs/heads/main/packages/%40mantine/core/src/component/InputBase/InputBase.tsx The above component and InputBase both use: https://raw.githubusercontent.com/paulm17/mantinesolid/refs/heads/main/packages/%40mantine/core/src/component/Input/Input.tsx Both InputBase in NumberInput and Input in the above component have a reactive value passed to them.
<InputBase
value={_value()}
<InputBase
value={_value()}
However both InputBase and Input do not give any feedback when createEffect is in play. With this in mind. Is there anything I can do to force some sort of logging? I've even tried to add value props to either InputBase and Input but then I have some sort of circular issue or infinite nesting. What can I do in this instance to debug? Thanks!
28 Replies
REEEEE
REEEEE4mo ago
My guess would be it's because of polymorphicFactory or another helper hook causing the breakage
REEEEE
REEEEE4mo ago
For example, the destructuring here
No description
Paul
PaulOP4mo ago
Thanks. Not sure why, but I was completely oblivious to when AI changed it for the last support issue. I suppose I was too focused in getting it to work for the last use case.
It works for polymorphic-factory. Now I have to work out factory. I just checked PinInput and that works too. 😮‍💨 Thanks for taking the time to check my work again!
Paul
PaulOP4mo ago
@REEEEE I updated polymorphic-factory: https://raw.githubusercontent.com/paulm17/mantinesolid/refs/heads/main/packages/%40mantine/core/src/core/factory/polymorphic-factory.tsx But InputBase is still not getting updates. I've logged out all the variables associated here. I've traced down useInputProps and any associated transformations and if they are destructured or not doesn't matter. I can't seem to track down why value loses reactivity. Could you take a quick look and maybe you can see what could be the issue?
bigmistqke
bigmistqke4mo ago
I am not sure if it will solve the bug but: return ui(props as Payload['props'], ref.ref); you are resolving ref here, this will be bugprone. accessing a prop outside of effect/memo has the same effect as destructuring
REEEEE
REEEEE4mo ago
Also, just for sanity checking, try to log out a specific property of the props in an effect instead of the whole obj. It won't react to the whole object
REEEEE
REEEEE4mo ago
Also the spreading here is probably breaking it too
No description
bigmistqke
bigmistqke4mo ago
ye, you wanna do mergeProps(rest, {...}) instead also i am not sure how you want inputProps to be merged, but it could be unexpected results. the way how it is setup right now it will either - set inputProps to these defaults if the user provided no inputProps OR - if the user provides a partial props.inputProps it will set it to this partial inputProps. it will NOT merge the partially provided inputProps with the defaults you set there. to do the latter you can do the following:
const inputProps = mergeProps({ required: local.required, ... }}, () => props.inputProps)
const inputProps = mergeProps({ required: local.required, ... }}, () => props.inputProps)
Paul
PaulOP4mo ago
@REEEEE @bigmistqke awesome thanks! I will take a look.
bigmistqke
bigmistqke4mo ago
(you might have to flip the order, i haven't really checked ur code out, but ig you get the general gist) (same for this one) (defaults go first)
Paul
PaulOP4mo ago
You both are solid wizards 🧙‍♂️ It was the
mergeProps(rest, {
mergeProps(rest, {
That broke it. I would have never changed it as to me it looks fine. 😩
bigmistqke
bigmistqke4mo ago
ye relying on ai for generating solid code can be a bit tricky
Paul
PaulOP4mo ago
I use AI sparingly as otherwise it would defeat the purpose of me trying to learn solid. Also there's maintenance which will need to occur when changes happen in the upstream react version. If I can't grok solid. I'm in a big jam 😆
bigmistqke
bigmistqke4mo ago
be aware of this too. this could cause very subtle bugs with conditional refs
Paul
PaulOP4mo ago
I'm trying to understand that and also the change you outlined here. https://discord.com/channels/722131463138705510/1375218305618542653/1375461709971722412
bigmistqke
bigmistqke4mo ago
so the 1 rule in solid is: if you access a prop outside of an effect/signal it will not be reactive. having a reactive ref is a , but imagine something like this:
const [shouldRef, setShouldRef] = createSignal(false)
const [ref, setRef] = createSignal()

setTimeout(() => setShouldRef(true), 1000)

// This will never log
createEffect(() => console.log(ref()))

return <div ref={shouldRef() ? setRef : undefined}/>
const [shouldRef, setShouldRef] = createSignal(false)
const [ref, setRef] = createSignal()

setTimeout(() => setShouldRef(true), 1000)

// This will never log
createEffect(() => console.log(ref()))

return <div ref={shouldRef() ? setRef : undefined}/>
this would not be reactive with your current approach as ref is resolved in the function body when you do ref.ref
bigmistqke
bigmistqke4mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke4mo ago
if you still want 1 single prop eventually you could do something like: https://playground.solidjs.com/anonymous/b7bc9012-b7d9-4360-ae20-a83efe06ccfc
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Paul
PaulOP4mo ago
Do I need to add value to this object for it to be tracked? I can see that within the inputBase, Input and box components. Value is being updated. But for the numberInput component, it stays static while the others update. Within the NumberInput component both _value() from the uncontrolled function and local.value track ok.
REEEEE
REEEEE4mo ago
You might not have to if you made the change that bigmistqke suggested but you could try it
Paul
PaulOP4mo ago
I fixed the polymorphic factory from before: https://discord.com/channels/722131463138705510/1375218305618542653/1375227600859041915
const Component = (<C extends ElementType = Payload['defaultComponent']>(
allProps: ComponentProps<C> & { ref?: Ref<Payload['defaultRef']> }
) => {
return ui(allProps as Payload['props'], allProps.ref);
}) as unknown as PolymorphicComponent;
const Component = (<C extends ElementType = Payload['defaultComponent']>(
allProps: ComponentProps<C> & { ref?: Ref<Payload['defaultRef']> }
) => {
return ui(allProps as Payload['props'], allProps.ref);
}) as unknown as PolymorphicComponent;
Which works for all components except the NumberInput. But I'm not sure I understand bigmistqke's playgrounds.
const Component = (<C extends ElementType = Payload['defaultComponent']>(
allProps: ComponentProps<C> & { ref?: Ref<Payload['defaultRef']> }
) => {
return ui(allProps as Payload['props'], () => allProps.ref);
}) as unknown as PolymorphicComponent;
const Component = (<C extends ElementType = Payload['defaultComponent']>(
allProps: ComponentProps<C> & { ref?: Ref<Payload['defaultRef']> }
) => {
return ui(allProps as Payload['props'], () => allProps.ref);
}) as unknown as PolymorphicComponent;
Is that what it should be changed to?
REEEEE
REEEEE4mo ago
Ideally yeah and you update anywhere that uses the ref argument to call it since it's now a function so it would be ref={ref()} instead
Paul
PaulOP4mo ago
So the () => is making the prop a derived function and telling solid, this is reactive?
REEEEE
REEEEE4mo ago
yeah
Paul
PaulOP4mo ago
Ok, got it. Thanks.
REEEEE
REEEEE4mo ago
Seeing as number input is made up of inputbase, and inputbase is working fine, I can't tell what's breaking there 🤔
Paul
PaulOP4mo ago
I can't seem to find it. I've spent all today trying to finish NumberInput and I'm going to leave it aside.
No description
Paul
PaulOP4mo ago
😂

Did you find this page helpful?