|
Hi, First experience with solid, sorry if the question seems trivial. I have a component that passes a state value to another component as a prop. However the inner component ( function App() {
const [state, setState] = createState({ progress: 0 });
const timer = setInterval(() => setState({ progress: (state.progress + 1) % 100 }), 50);
onCleanup(() => clearInterval(timer));
return (
<div class='App'>
<Button progress={state.progress}>
Progress Button
</Button>
</div>
);
}
function Button({ children, progress }) {
return (
<button class='Button' data-progress={progress}>
{children}
</button>
)
}DOM value for return (
<div class='App'>
<Button progress={state.progress}>
Progress Button {state.progress} <------ This updates
</Button>
</div>
); |
Replies: 4 comments 8 replies
|
No problem. And there is luckily an easy solution. Unfortunately you have run into the likely biggest gotcha with the approach Solid uses. This is shared by Vue and MobX too. We can't destructure props without losing reactivity. The button component needs to look like: function Button(props) {
return (
<button class='Button' data-progress={props.progress}>
{props.children}
</button>
)
}I've tried to note this in the docs in several locations but I feel like it's a 50/50 whether people see this. More detailed explanation: It isn't the destructure itself doesn't work. It is that tracking for updates happens on property access, so if you reference them outside of a JSX binding or a "hook" (reactive primitive) no one is listening. The granular reactive approach we use doesn't re-render whole components but only the hooks and the JSX expressions so tracking only occurs in them. This is a key part of the performance and the approach we use to avoid diffing (and VDOM) but it does bring this caveat. As for Component props they lazily evaluate. So when you pass Hope that helps. |
|
I have run to this problem. But mine is a little different. I have created a signal, and I call the function for getting the signal in the JSX. The underlying component expects In my component, in the beginning, the messages are If I replace export default function PanelComponent(props: Props) {
const [getMessages, setMessages] = createSignal(props.delegate.filteredMessages)
onMount(() => {
props.delegate.onDidChangeMessages(messages => {
setMessages(messages)
})
})
/// other code here
return (
<div>
<SimpleTable
rows={getMessages()} // only called once in the beginning.
/// other props here
/>
</div>
)
} |
|
I got stuck for about 45 minutes today with this exact issue. I'm curious what the solution is when you need a rerender like you would get in React. I have resorted to just using components as functions rather than tags and it works but it's not great. So: The tag for Printer doesn't work but using it as a function does. I have looked through the documentation the best I can but I can't seem to figure how what you are supposed to do here. I tried useEffect and a bunch of other stuff. Any insight or pointing to the docs would be great. |
|
@MattStopa Something like this? |
No problem. And there is luckily an easy solution. Unfortunately you have run into the likely biggest gotcha with the approach Solid uses. This is shared by Vue and MobX too. We can't destructure props without losing reactivity. The button component needs to look like:
I've tried to note this in the docs in several locations but I feel like it's a 50/50 whether people see this.
More detailed explanation:
It isn't the destructure itself doesn't work. It is that tracking for updates happens on property access, so if you reference them outside of a JSX bin…