How can I allow a Vue component to manage its own transitions? - javascript

By this I mean, when mounted, the enter animation is ran, and when removed, the leave animation is ran. I have a transition that needs to animate a number of elements within it on enter and leave, so I want to move all the code into its own component, then
<template>
<transition #enter="enter" #leave="leave">
<!-- component -->
</transition>
</template>
---
<CustomComponent :key="indentifer" :indentifer="indentifer" />
Full example of my attempt: https://codesandbox.io/s/znq6l8p94p
As far as I am aware this is only half working because of the appear, i.e. it's just mere coincidence.
I feel like the only way I can solve this is by doing all the animation and state management in one component, as in a component that knows about the old and new sentences or use a transition-group, rather than just leaving Vue to manage that for me via my use of the key attribute. Am I perhaps misunderstanding how best to do transitions in Vue, should the animation all ways reside with the parent of a component?
After writing this out it feel like what I actually want is lifecycle hooks like transition-group offers, but which call the child components methods directly.

My current understanding is that during v-on:leave the component is no longer reactive, and you should only be doing manual dom-manipulation...
Instead, my solution was to create a component that handled the adding and removing of the elements via a watch and then passed the array through to my component in props.

Related

React: Component Hide/ Show vs Destroy/ Recreate

Usually when we create conditional components, we do
{ condition ? <Comp1 /> : <Comp2 /> }
My question is, what is better approach?
Hide/ Show components using CSS?
Destroy/ recreate components?
My assumption is, Hide/ Show would be a little better as you will have to go not through creating components again. Just repaint and reflow.
One scenario I can think of that would be an issue with destroy/ recreate would be when you save internal states. This can be achieved using a state management system by passing props. The thing I'm not sure is, if we keep stale components in VirtualDOM and if these components are heavy, like a grid, it will affect the performance but it might still be less than creating the entire component again. So does it makes sence to destroy components?
Not considering React.memo hook, as a caching + recreate will be better. So for a non-hooks based application, what would be a better option?
In my opinion, cuz when React to do DOM diff, it will reduce useless DOM count. If u using class to control that, React will do some extra work

How to create a badge component for custom components?

I am facing a really nasty issue, I need to create a badge component that it'll be places over a custom component.
This is my first attempt to create something similar in React, with HTML is way easier because you work directly with the DOM.
In this case instead I need to create a badge that will highlight a new component/feature, when you click on it a popup get's open with a bit of text that'll explains what the component is about, aka it's functionality. Telling you this because I need to listen for onClick and it's not possible to use pseudo-elements.
The base idea
<BadgeComponent position="top left">
<CustomComponent />
</BadgeComponent>
Since I can't use a pseudo-element that'll inherit all the element CSS properties this is my thinking:
do not change the CustomComponent because each time could be different
the BadgeComponent is a wrapper that creates a div with position:relative (so I can position the badge wherever I want)
BadgeComponent needs to be display: inline-block otherwise it'll change the overall layout
I need to take the CustomComponent box-model properties, remove from it and apply them to the BadgeComponent. This mostly because margins are messing with the BadgeComponent size and position the badge itself will be trickyer
Basically I need to take the CSS properties of the DOM element rendered from the child component.
The approach
So I've been experimenting with some code before came here and my first attempt has been to dinamically pass a ref to the child component of BadgeComponent with this snippet:
{React.Children.map(this.props.children, (element, idx) => {
if (idx > 0) return; // don't care if it has more childrens, at least for now.
return React.cloneElement(element, { ref: this.newFeature });
})}
I also thought to take the CustomComponent as a prop of BadgeComponent, like so:
<BadgeComponent position="top left" target={ CustomComponent }>
But I didn't (yet) followed this path because I thought that at the end of the day this.props.target it's basically the same of this.props.children and didn't earn anything doing so. Am I right?
I know that in React we have ref to get a reference to the DOM created from a component but in this case is not applicable because I am not applying the ref to the component that renders an HTML, I am applying it to CustomComponent that gets cloned and it doesn't pass to the DOM.
From my experiment everything works fine if I pass an HTML element, in the experimental code I have a div.box that gets the badge in the position that I want but as soon as I pass the Button I got the following error: Window.getComputedStyle: Argument 1 does not implement interface Element.
I am using window.getComputedStyle to get the CSS properties I care about.
My research
I've been looking all around the web and I've seen a nice implementation that, unfortunately, just works with styled components or styled defined inline in <style>. I am looking to not use NPM packages as this one because firstly I believe that it is possible to implement without reach for an additional package and second actually I do not like much the way that the sticky/badge get's implemented (with all respect obviously).
I don't know where to look anymore, I am not an expert JS/React developer (been WP theme developer for 10 years) so probably there is some basic concept that I missunderstand?
I've read about findDOMNode (looks will be deprecated soon) and forwardRef in the React ecosystem but I do not think that's the way to go, am I wrong?
I do not want the copy/paste code, well if you're so gentle to fork the codesandbox and share the solution will be great but I am trying to learn here: there is a way to get a reference of the rendered HTML element from any component?
Thinking that this is the missing part, if I can reach the DOM my code is already working 😊

How does Animated.Component / createAnimatedComponent(Component) differ from Component?

We are trying to figure out cause of following issue from styled-components project: https://github.com/styled-components/styled-components/issues/389
There were some changes made to refs + setNativeProps that broke animation in one place, assumingly because some animated related information is not being passed down correctly.
Hence the question to understand how createAnimatedComponent alters initial component, whats added? What could cause animation to break if not passed down correctly?
Please provide ideas / detailed answer if you know what could be causing this issue.
UPDATE
Breaking change related to the issue occurred somewhere within this file for reference innerRef passes down ref, isTag function checks if it is a native component.
animatable components can be animated. View, Text, and Image are already provided, and you can create custom ones with createAnimatedComponent. These special components do the magic of binding the animated values to the properties, and do targeted native updates to avoid the cost of the react render and reconciliation process on every frame. They also handle cleanup on unmount so they are safe by default.
https://facebook.github.io/react-native/docs/animated.html

How to preserve a component's instance while moving it to another parent component in react?

Suppose we have two sibling react components called OldContainer and NewContainer. There is a child component inside OldContainer that contains a <video> tag, and the video is currently playing.
The user can now drag the child component (with the video) and drop it in the NewContainer, and they expect the video to keep playing while it's being dragged and after being dropped.
So the video appears to stick to the mouse position, and when dragged and dropped in the new container, it animates to its new position (again, it doesn't get paused).
How would you implement this? Can we implement this in a pure way (in line with the spirit of pure functions)?
Clarification: I could have used some other element instead of a video tag for explaining this problem. A NumberEasing element would be a better example, since it would require the props and state of the component to be preserved during and after the interaction.
Update 1: Code examples obviously would be nice, but what I'm mainly looking for is just a general description of how you would approach this problem in a "functional" way. How do you keep your view code simple and easy to reason about? Who handles the drag-and-drop gesture? How do you model the data that's fed into the views?
Take a look at this library : react-reverse-portal
What is it that you want to preserve? Is it Javascript objects that the component holds as state, or is it state in the DOM (like how long a video has played, or text selection in an input box)?
If it's just Javascript objects as state, you're better of moving the source of that state to another service (something like Flux). That way, it doesn't matter if the component gets recreated because it can be recreated with the state that was there before.
EDIT
The way to keep your view code simple and easy to reason about is to not keep state inside your components. Instead, all data that the component needs should be passed into the component as props. That way, the component is "pure" in that it renders the same output given the same props. That also makes the problem of wanting to reuse a component instance a non-issue, since it doesn't matter when the same input gives the same output.
For drag and drop, I'd suggest looking at: https://github.com/gaearon/react-dnd.
How you model the data you pass to view components is up to you and the needs of your application. The components shouldn't care, they should just expect to get data passed as props, and to render them. But the popular approach to dealing with this is of course Flux, and there are many libraries that implements Flux in different ways.
SECOND EDIT
Regarding if you have a subtree with hundreds of components that you want to move: I'd still start off by making the state external (pure components), and render that tree in a new place. That means that React will probably recreate that entire subtree, which is fine. I wouldn't deviate from that path unless the performance of it turned out to be horrible (just guessing that it might be horrible isn't enough).
If the performance turned out to be horrible, I would wrap that entire subtree in a component that caches the actual DOM tree and reuses it (if it gets passed the same props). But you should only do this when absolutely needed, since it goes against what React tries to do for you.
THIRD EDIT
About gestures: I'd start out with listening to gesture events in componentDidMount, and in the event callback call setState on the component with the coordinates it should have. And then render the component in render with the coordinates given. React won't recreate the component when you call setState but it will re-render it (and diff the output). If the only thing you changed was the coordinates, it should render fast enough.
If that turns out to be too slow, like if the subtree of that component is huge and it becomes a bottleneck to recreate the subtree of vDOM, I'd reposition the DOM node directly in a RAF-loop outside of Reacts control. And I'd also put a huge comment on why that was needed, because it might seem wierd for some other developer later.
Create a new variable using const or var. Put the instance of data using rest spread operator, update the necessary data to pass and send the data to the component without mutating the state of component.
Just like:
const data = {
...this.state.child,
new_data : 'abc'
}

Simple React.js implementation

I have a relatively simple app with a header and a main section of content. The main section can show up to 4 different types of components, but only 1 component at a time. Each component needs to have the ability to transition (slide) from one component to the next depending on the state.
As of now my main application component holds the state as to which component should be shown. This main application component also renders all 4 of the top level components. Each of the 4 top level components hide/show themselves based upon the application state. Is this the best way of toggling the different components on and off, or should I manually mount and unmount each component? If I take the mount/unmount approach am I still able to easily transition each element?
I would have upvoted or commented on Douglas' answer but I dont have enough rep!
ReactCSSTransitionGroup will do what you want. Adopt the tutorial example to suit your purposes and dont forget to write your animation styles first (ReactCSSTransitionGroup relys on CSS animationend callback to know when the elements have left/entered the dom). It will add helper classes for you so you can create a transition effect between the (incoming and outgoing) elements.
A ReactCSSTransitionGroup will probably do what you need, at the very least you could look at the implementation to see how they do it.

Categories

Resources