New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useEffect #3
base: main
Are you sure you want to change the base?
useEffect #3
Conversation
What's the use case for mountEffect? Why not just call it in the constructor? |
It's especially will be useful after #4
So it will be an ideal replacement |
Case number 1 is covered better by modifiers as they directly affect elements. |
Right now - yes. You have to use
the effects fully cover the situation:
Without the effects, you have to use both modifiers and write all consumers in the template which tears the logic |
Actually no. Did-insert and did-update are crutches that you should only use for very very simple cases. For Dom mods you should use a custom modifer 'Ember g modifier draw-graph' Put an effect in that modifier to call play on the video for example, then attach the modifier to the video element |
A custom modifier doesn't help if you need some control via actions, buttons from this component or any child components, or even from some models if the logic is complex |
One thing Ember is very good at is providing one way to do a particular task. If you need a button to trigger something, do that in the button action. If you need to call a method on an element, do that in a modifier that contains the logic and is passed the tracked data it needs to make the decision. The one place that you can't call a method from a data change is a service, where there is no render context. Modifiers and effects do the same thing - they turn a change event into a method call. Modifiers are linked to an element, effects are not. We shouldn't pollute that by having effects that are linked to elements as you seek to be suggesting. |
Modifiers are good for something very simple. But when it becomes a little bit harder, you are stuck, because there is no good way to do it. If you need to trigger something on the element from the button or the input, of course, you can create a batch of tracked properties and put them into the modifier. But if you need to have them bi-directional (for example My vision is to have the effects to use them both for something very simple and something complex. And my suggestion is not to link them to elements, but give them that lifecycle that doesn't limit you. So the effect is called would mean that one of the dependencies is updated so its related computed properties and its related components are updated, so it would be safe to update new properties/read the dom elements properties/call the element's methods. I agree that an empty array in dependencies is a rare case, but the deps also cover it without any problems |
I think you're describing what I've done. The only big difference is that I forgot to put the effect callback into the actions queue. I've just added that. My original design took a list of observed properties, like yours, but the discussion here was to get rid of that because they were automatically entangled in the function. What's a use case for using a value in the function but not wanting to entangle it? Not just not needing to, but specifically not wanting to have it rerun the function. |
Ok, there are some examples where you can stuck without clarifying the deps.
It can be a real problem if you have some this or some tracked counter (
Also, another benefit is typescript coverage, as this code
can be surprise as |
The main reason I want to have it there is
deps
function to control the effect explicitly and say when this effect should be called. Another reason is a full typescript coverage, as there are no decorators and no implicit type changes.Usage:
useEffect
can be autotracked or controlledTo have a controlled effect you'll need to pass the
deps
function (() => [trackedProp1, trackedProp2]
). If any of these properties is updated it'll trigger the new effect.Note, the property can be updated, but the value can be the same (
this.prop = this.prop
), it'll trigger the effect anyway. To prevent this you can use thededupeTracked
decorator from https://github.com/tracked-tools/tracked-toolbox instead.To have the effect on mount only, pass the function with empty array (
() => []
).Passing non-tracked properties to this array has no effect on updates.
The deps array is also passed to the effect function as arguments. (
useEffect(this, (prop1, prop2) => {...}, () => [prop1, prop2]
)If you don't pass the deps argument, the effect will be autotracked, so it will trigger the function whenever any tracked property in the effect is updated.
Be careful with this effect if you are using more than 1 tracked property inside the effect as it can be complicated to investigate what property triggers the update. Use controlled effect there instead.