I am trying to animate a React component that contains data fetched from elsewhere. Placing it in a ReactCSSTransitionGroup worked fine. That is, until I altered the component's render() method to return false until the data has been fetched (to prevent it from being rendered without data).
Now, I guess the component is mounted immediately, at which point the animation classes are added, but only rendered afterwards. Is this thinking correct? How can I get the component to be animated when render returns the actual component?
ReactCSSTransitionGroup activates whenever components are added and deleted to its props.children. Since your component is mounted before you fetch data, nothing will happen after data is fetched (I think this is true even if the component's render() method returns false. Let me know in the comments if that is incorrect)
Here's a solution
Just don't mount the component (in the solution, it's a <div key="1"> tag) until the react class receives the data. Use component states on the parent component to keep track of the state of your asynchronous request.
The ReactCSSTransitionGroup doesn't play nicely with tables as it's default behaviour is to wrap tags with a span element. You can provide it with your own component, but I found the solution quite heavy and complex.
I have a different approach that allows a React component to animate each time its content changes. The animation is continually triggered by toggling between 2 duplicate CSS styles.
Other than the ReactCSSTransitionGroup, another way is to write your own css transitions with an 'enter' class that is added to the component in componentdidmount. Keep in mind that you should change the state in a requestAnimationFrame because otherwise your class would be added in the same event loop as it is mounted, thus wont animate. Here's an example:
https://codesandbox.io/s/zkm5015y1x
Also, more on event loop, a talk by Jake Archibald:
https://www.youtube.com/watch?v=cCOL7MC4Pl0
Related
I have a component that is using React Transition Group to animate a component as it changes from one component to the next.
The problem I am having is that the next component is loading before the current animation is finished, so it looks a bit odd.
I think i could solve this if it were possible to delay the render() method when the component updates, as it never really unmounts, and this is why the component flashes the next image.
there is FAR too much code involved to paste it all here so i made my github public, and created an issue there to show what I am experiencing.
also you can view the site as it is live for this debugging session.
stevensheaves.me
Also, no judgy, its not 100% finished.
You can simply use the callback of the Transition Group namely onEntered.
A callback fired immediately after the 'enter' or 'appear' classes are removed and the done class is added to the DOM node.
You can use a flag variable to display your content. Set it to true when the callback is fired and to false when it's onEntering
In Angular to change the styling of an element or component I understand there are tools available in the form of directives (ngStyle, ngClass). However as far as I can tell, ngClass allows for conditional styling only in which one changes styling based on a particular scenario. These are therefore changes based on discrete conditions.
ngStyle allows an object to be passed which can in theory do this by returning a style object which is custom defined, but then ngStyle is listening perpetually to page changes, whereas I wish to trigger the style change when a specific action occurs, instead of listening to all page changes if possible?
I would like to programmatically change an images's css properties programmatically (rotation, width, height, opacity) based on perhaps a button press, or a mouse event, or just when a function is called, but the key is I want those changes to be continuous, for example, a rotation based on a variable in the component class, no discrete options of class changes.
In Angular, how would this be done? ViewChild allows access to the DOM and therefore the styling, but the styles are read-only it would seem as they are computed.
I can't post code, as I don't know where to start to make such a thing work.
but then ngStyle is listening perpetually to page changes, whereas I wish to trigger the style change when a specific action occurs, instead of listening to all page changes if possible?
That's the whole point of Angular: you bind data to the view via a declarative template syntax it offers, and let it figure out when to update.
If you try to trigger update by manually knowing when data changes, you're probably doing something wrong (or you're optimizing a specific part of the library). Letting Angular do the update is the correct thing to do.
update () {
this.styles = { /* ... */ }
}
<div [ngStyle]="styles">...</div>
I have a parent component with a people property. It uses a Service to get people Observable .
Then I have several children components. Everyone has #Input people from parent component. (To avoid http request on every child)
I would like to modify people array in each Child component without affecting the others (parent component and other child component)
It would be something like a new Observable copy or get data from observable.
I need the initial value of people in all components, but then I need to modify for each one.
How can I do this?
Thank you.
Do you need the people object to be an Observable in the child components? If this is not the case, you might want to change your code a bit. Instead of passing the Observable to the child components, just pass along the initial data via #Input()-Binding.
I need to completely initialize a custom component in my Flex app (i.e. I should be able to access it from action script and get its properties and its children etc), But I do not want to add it to the display or make it visible.
I have tried to add it to my visible component, but keep it visible, but often many of its properties are set only when it is drawn, so i don't get what i need.
Is there a way to add a custom component to some sort of 'Virtual' display, that is not visible to the user?
You could add the component to an invisible Sprite - that way the component itself could both be on the stage and have its own visible property set to true.
Did you try using initialize()? After a view is added to the display list, the initialization stage begins. Calling initialize() before addChild() should let you initialize the view without needing to first add it to the stage.
For more info visit:
http://flexscript.wordpress.com/2008/10/24/flex-component-lifecycle-and-flex-component-framework/
http://blog.deadinkvinyl.com/2008/10/05/flex-3-addchild-and-initialize/
Not sure if possible without adding it to the display list, although I'd wish it were to some extent.
I once had to make custom drag proxy, which didn't work with the real component, because of some weird skinning issues. So instead I had PopupMananger add a box as a popup, added my component to the box, called validateNow on the component, drew it in a bitmap data, removed the popup, and used the bitmap data as the proxy.
So what you were trying was missing a call to validateNow most likely.
Can anyone think of a (preferably quick) way to move the data() attached to a DOM element to a new instance of itself?
The lightbox plugin I'm using deletes and re-appends and element to the page in order to display it in the lightbox (to aviod the multiple-ids issue that ASP.net has), and obviously the .data() that is attached to the element is lost when this happens.
There's a relatively new overload for .clone() you can use to do this.
.clone(true) will copy the element with events and data intact.
Alternatively, change your plugin to use .detach() rather than .remove() which keeps data intact. From the docs:
The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.