S
SolidJS3w ago
Paul

Not understanding signals

I have this component:
const [opened, setOpened] = createSignal(false);

createEffect(() => {
console.log('parent opened: ', opened());
});

return (<>
<div style={{ 'padding': '40px' }}>
<Burger opened={opened()} onClick={() => setOpened((o) => !o)} size={400} lineSize={1} />
</div>
</>)
const [opened, setOpened] = createSignal(false);

createEffect(() => {
console.log('parent opened: ', opened());
});

return (<>
<div style={{ 'padding': '40px' }}>
<Burger opened={opened()} onClick={() => setOpened((o) => !o)} size={400} lineSize={1} />
</div>
</>)
See parent opened being reactive just fine. 😄
export const Burger = factory<BurgerFactory>((_props, ref) => {
const props = useProps('Burger', defaultProps, _props);
const [local, others] = splitProps(props, [
...
'opened',
...
]);

If I put a createEffect here. I don't see anything at all.

createEffect(() => {
console.log('opened', local.opened()); <-- have tried many combinations here
});

return (
...
<Box mod={['reduce-motion', { opened: () => local.opened! }]} {...getStyles('burger')} />
{local.children}
...
);
});
export const Burger = factory<BurgerFactory>((_props, ref) => {
const props = useProps('Burger', defaultProps, _props);
const [local, others] = splitProps(props, [
...
'opened',
...
]);

If I put a createEffect here. I don't see anything at all.

createEffect(() => {
console.log('opened', local.opened()); <-- have tried many combinations here
});

return (
...
<Box mod={['reduce-motion', { opened: () => local.opened! }]} {...getStyles('burger')} />
{local.children}
...
);
});
Note for opened: () => local.opened!
opened: local.opened
opened: local.opened()
opened: () => local.opened
opened: () => local.opened!
opened: local.opened
opened: local.opened()
opened: () => local.opened
opened: () => local.opened!
Whatever I try. I just don't get any feedback. What am I missing? The docs are a little too basic. I understand signals when all the code is centred within 1 component. Now a nested setup. I am lost. Thanks! And please ELI5 it for me 😂
8 Replies
REEEEE
REEEEE3w ago
what is useProps doing
Paul
PaulOP3w ago
import { filterProps } from '../../utils';
import { useMantineTheme } from '../MantineThemeProvider';

export function useProps<T extends Record<string, any>, U extends Partial<T> = {}>(
component: string,
defaultProps: U,
props: T
): T & {
[Key in Extract<keyof T, keyof U>]-?: U[Key] | NonNullable<T[Key]>;
} {
const theme = useMantineTheme();
const contextPropsPayload = theme.components[component]?.defaultProps;
const contextProps =
typeof contextPropsPayload === 'function' ? contextPropsPayload(theme) : contextPropsPayload;

return { ...defaultProps, ...contextProps, ...filterProps(props) };
}
import { filterProps } from '../../utils';
import { useMantineTheme } from '../MantineThemeProvider';

export function useProps<T extends Record<string, any>, U extends Partial<T> = {}>(
component: string,
defaultProps: U,
props: T
): T & {
[Key in Extract<keyof T, keyof U>]-?: U[Key] | NonNullable<T[Key]>;
} {
const theme = useMantineTheme();
const contextPropsPayload = theme.components[component]?.defaultProps;
const contextProps =
typeof contextPropsPayload === 'function' ? contextPropsPayload(theme) : contextPropsPayload;

return { ...defaultProps, ...contextProps, ...filterProps(props) };
}
I thought I had used splitProps on this, but may have missed it. 😩
REEEEE
REEEEE3w ago
It's the spreading of the props that's probably breaking it try using mergeProps with splitProps instead to do that return
Paul
PaulOP3w ago
I finally have feedback 🥳
const theme = useMantineTheme();
const contextPropsPayload = theme.components['Burger']?.defaultProps;
const contextProps =
typeof contextPropsPayload === 'function' ? contextPropsPayload(theme) : contextPropsPayload;

const props = mergeProps(defaultProps, contextProps, _props);
const theme = useMantineTheme();
const contextPropsPayload = theme.components['Burger']?.defaultProps;
const contextProps =
typeof contextPropsPayload === 'function' ? contextPropsPayload(theme) : contextPropsPayload;

const props = mergeProps(defaultProps, contextProps, _props);
Now I have to figure out how to get use-props to work. What do you mean using mergeProps with splitProps? 🤔 If I pull useProps into the component. I get reactivity. If I have
return mergeProps(defaultProps, contextProps, filterProps(props)) as any;
I get no reactivity. 🙁
REEEEE
REEEEE3w ago
It's probably the filterProps that's breaking it What does it do?
Paul
PaulOP3w ago
export function filterProps<T extends Record<string, any>>(props: T) {
return Object.keys(props).reduce<FilterPropsRes<T>>((acc, key: keyof T) => {
if (props[key] !== undefined) {
acc[key] = props[key];
}
return acc;
}, {} as FilterPropsRes<T>);
}
export function filterProps<T extends Record<string, any>>(props: T) {
return Object.keys(props).reduce<FilterPropsRes<T>>((acc, key: keyof T) => {
if (props[key] !== undefined) {
acc[key] = props[key];
}
return acc;
}, {} as FilterPropsRes<T>);
}
So to me that looks fine. But why doesn't solid like it? Btw, I removed filterProps and it works. That is the culprit.
REEEEE
REEEEE3w ago
reading the prop outside of a reactive context just gives the initial value of the prop. You're basically destructuring through that helper. It's like if you have an object and you destructure it like this:
let count = 0

const obj = {
get someKey(){
return count
}
}

const { someKey } = obj

count += 1

// Always 0
console.log(someKey)

// Prints 1
console.log(obj.someKey)
let count = 0

const obj = {
get someKey(){
return count
}
}

const { someKey } = obj

count += 1

// Always 0
console.log(someKey)

// Prints 1
console.log(obj.someKey)
Solid transforms it's props into object getters
Paul
PaulOP3w ago
Finally got this to work. Just now remembered to update the thread: 😩 use-props.ts
return mergeProps(defaultProps, contextProps || {}, props) as T & {
[Key in Extract<keyof T, keyof U>]-?: U[Key] | NonNullable<T[Key]>;
};
return mergeProps(defaultProps, contextProps || {}, props) as T & {
[Key in Extract<keyof T, keyof U>]-?: U[Key] | NonNullable<T[Key]>;
};
I went with props instead of filter(props) as then I would lose the reactivity and I just couldn't get a working solution. No matter what I tried. 🤷‍♂️

Did you find this page helpful?