-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
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
Feature Request: React like hook shouldComponentUpdate for Vue lifecycle #4255
Comments
|
@yyx990803 thanks for the reply,
I like that Vue automates the rendering of the correct components, but I believe it makes sense to have an option to circumvent that behavior if desired. I believe exposing such an option/hook would open Vue up to the use of contenteditable, provide potential for performance boosts, and solve my headache :) |
Hi, v-once might be helpful here. https://jsfiddle.net/he1ug0fo/ If you still need more fine grained control over rendition, one more computed getter might be helpful.(For example, For general cases, computed properties that gets selectively updated might be enough for implementing |
@HerringtonDarkholme thanks for the direction! you are correct, The original JSFiddle you updated did not work correctly because it was using older versions of Vue and Vuex. I have created another JSFiddle with Vue and Vuex 2.0 which demonstrates the updated functionality. Your suggestion of a computed property makes sense to me if I intended to display the content separately through the template, however that part of the JSFiddle was just for example purposes. I still believe a Your I would still be interested in seeing a |
After looking at your use case, I still don't think The fully framework-compliant way to deal with it (and is also what I would suggest even in React) is to have a separate piece of state that represents the input content, which can then be out of sync with the model state and can be updated only when you want to. |
I just found a case which You can see the dev console. Every time you click on a tab, all other tabs will re-render because they depend on So in this case, even all the props are the same, the components will still update itself. If we want to optimize the performance, |
@CodinCat in this case the tabs are forced to update because they have slot children. Technically, this means if you implement a In React, if you use a pure component for this purpose, it will also always re-render because the Of course, you can try to diff the children nodes in a custom |
+1 shouldComponentUpdate might be added only to Render Functions & JSX section. |
@yyx990803 How would you recommend passing 60-changes-per-second data from a parent to a DOM heavy child that can't render at 60fps (and only needs to render at 1fps)? I'm currently wrapping the data-from-parent in a function and then having the parent change/refresh that function when the child should be updated, but it is less than ideal and circumvents the normal flow of Vue. I don't see how a separate piece of state would handle this situation. ScenarioI have edit: improve clarity/wording |
I sometimes come across threads like this in the open-source world, where a person requests a feature like computed re-render, and others jump in to tell them they're doing it wrong. I always feel like this misses the point: As developers, we need power tools. We need the power to tell the system what to do. |
While I do agree (in general) with you @glassdimly, and I love the ruby programming language for following the assume-the-dev-knows-best paradigm, Vue.js does have a responsibility/goal to be minimal. I don't want a fix like For example, maybe it would be better for there to be a However, I still would like to know how @yyx990803 or anyone else would recommend passing rapidly-changing data to a component that needs to render less-rapidly. |
I think your second paragraph makes a very good point @jeff-hykin which no one should overlook. I learned Vue first before learning React, and when I discovered that React didn't actually react to my data changes automatically (à la Vue), I was flabbergasted. How could something so "revolutionary" require such a primitive hack.
As for solutions to the problems outlined in this nearly 4-year-old topic, you are basically looking at a throttle or debounce. This is not strictly a Vue problem/solution. It is, however, a problem which can be solved in a userland component: <template>
<div>Slow data: {{ throttledData }}</div>
</template>
<script>
import throttle from "mout/function/throttle"
export default {
name: "ThrottledDataView",
props: {
data: { type: Object, required: true }
},
data: () => ({
throttledData: null
}),
created() {
const vm = this
const throttledUpdate = throttle(
(newData) => (vm.throttledData = newData),
1000
)
vm.$watch(() => vm.data, throttledUpdate, { immediate: true })
vm.$on("hook:beforeDestroy", throttledUpdate.cancel)
}
}
</script> Vue's |
I agree with you @jeff-hykin. One doesn't want to implement a In React, whenever state changes, it triggers an update--similar to Now, throttling component updates is great (
|
Here's something interesting I pulled verbatim from that section of the docs (emphasis mine):
React shouldn't be your metric for what is "right". It is full of workarounds such as As I've demonstrated in my previous comment, there is a clear, and elegant solution with a clear data model and lifecycle. I don't feel the core developers need to explain why they're not creating more footguns. Even though JavaScript the language provides many of them, I find it refreshing that Vue.js helps me enforce clarity in my work. I'm out. Have a great week, and stay safe! |
@sirlancelot: Respectfully, it's important to have experience with the frameworks you critique. |
Thanks @sirlancelot , I've actually used debouncing before but did not think of it in this situation. I'll see if I can make a version of that solution that works, but my concern is that assigning to the this.throttledData won't help because the data is an array. The value doesn't ever change, it just gets mutated by adding more data. The simple workaround is to deep copy, however that is also an issue because it results in O(n) operation and the array is very large (hour-long video data). There would need to me a more complex solution such as diffing all the values that had been added in the time since the last throttled change, which gets complicated quickly. Wrapping the data inside function that can be called when needed is a, still non-ideal, but less complex solution. |
@glassdimly My first web framework was React, I spent 1.5 years using it in work and school before I found Vue. I'm all too familiar with Using React at work, we decided to use
I agree the debouncing seems very much like a large workaround. However, I actually like the option of I'm a Texan, I believe in the right to shoot myself in the foot if I so desire, and I have successfully used I want fine grain control as well, but I want to easily control render times AND do it without breaking any principles.
I do agree that first hand experience is needed before critique. (And I think you handled that point professionally @glassdimly.) Although I do agree with @sirlancelot that React is littered with workarounds (including shouldComponentUpdate) that point is largely irrelevant here as there are a number of things, such as functional components with JSX, that I believe Vue could learn from React. |
I think it would be useful to have a hook like React's shouldComponentUpdate in the Vue lifecycle. The idea behind this hook would be to dynamically prevent the DOM from refreshing the component with data change.
For my use case I am attempting to build a component that uses Contenteditable as a text editor interface which updates on keyup. The DOM refresh in the lifecycle results in the caret / cursor resetting with the refreshed component. Having the option to define when the component should update would allow use of Contenteditable while continuing to update the state (vuex) and keep any of the component {{references}} in the template reactive.
From my understanding of React, the ability to make re-render conditional would also be a big performance booster for components with lots of DOM refreshes like my example above. I'm a big fan of Vue and I think adding this lifecycle hook would open up a lot of doors.
The text was updated successfully, but these errors were encountered: