Closed isolin closed 1 year ago
Are you using React or Preact?
You should be using the hook versions (useX
) in function components, and the non-hooks in class components. React limits hooks to function components, you cannot use them in class components. Preact does allow you to use hooks in class components, but it's quite unidiomatic and I'm not sure if support is guaranteed long-term.
I am of course using preact. I just tried to follow the docs where useSignalEffect
is mentioned. I haven't been able to make it trigger, so I have rebuilt my components to functional. Nevertheless, I consider class components more verbose and easier to understand as the naming like componentDidMount
and componentWillUnmount
is much better for understanding and maintenance than having an useEffect
with the destructor being returned.
I am of course using preact.
Both React and Preact are supported, so that bit was unclear.
Nevertheless, I consider class components more verbose and easier to understand as the naming like componentDidMount and componentWillUnmount is much better for understanding and maintenance than having an useEffect with the destructor being returned.
Use what you prefer, that's not an issue. Just you shouldn't really be using hooks in class components.
The issue is that you're misusing useSignalEffect
, if your snippet isn't a typo. It's not a lifecycle method, but a function that takes a callback, just like useEffect
and effect
. Try this:
useSignalEffect(() => {
console.log(appstate.data.value.length);
});
Ah that was not clear to me. I thought it is a lifecycle method! I wrongly interpreted the following docs line
When responding to signal changes within a component, use the hook variant:
useSignalEffect(fn)
.
as being a lifecycle method in class components.
So just out of curiosity - is there any concept that I could use within a class component to handle updates in signal values?
as being a lifecycle method in class components.
Hooks are in contrast to life cycle methods. Very different things, and APIs.
Again, Preact sorta blurs the lines by technically allowing hooks in class components, but generally should be avoided as it's quite unidiomatic.
So just out of curiosity - is there any concept that I could use within a class component to handle updates in signal values?
I'm not really sure what the idiomatic solution is here, but this works I suppose?
class CheckBox extends Component {
#checked = signal(this.props.checked);
#_void = effect(() => console.log(this.#checked.value));
toggle = () => {
this.#checked.value = !this.#checked.value;
}
render({ label }) {
return (
<label>
<input type="checkbox" checked={this.#checked} onInput={this.toggle} />
{label}
</label>
);
}
}
Keep in mind, you only need to do this if you're creating the signal that needs to be watched inside the component. If your state can be external (like it doesn't need to be initialized by a prop), it can be a bit simpler:
const checked = signal(false);
effect(() => console.log(checked.value));
class CheckBox extends Component {
toggle = () => {
checked.value = !checked.value
}
render({ label }) {
return (
<label>
<input type="checkbox" checked={checked} onInput={this.toggle} />
{label}
</label>
);
}
}
I rather thought of something like:
const data = signal([1,2,3]);
class CheckBox extends Component {
process = effect(() => {
//some heavy processing specific for this component
this,state.data = this.process(data.value);
});
}
I need to process data before rendering them and a computed signal makes not much sense as
render()
function but instead it is fed as scene data to a THREE.js scenebut that is my specific use case. The above concept with process = effect(() => { /*...-* })
seems to work in class components and I anyway switched to functional in the meanwhile :)
This is probably some issue on my side, but I would be very glad if anyone could help me fixing it.
To Reproduce
I have a global state
When I reassign the data
state.data.value = [0, 1, 2]
the event is propagated only partially. If I have a functional component,effect
works.But when I use a class
Component
instead, thenuseSignalEffect
never triggers. Why so? Did I forget about something?Maybe an important info: the class component is created as
tableRef = createRef<SceneTable>()
in a parent class component, while the my test with the functional component was stand-alone.