React lifecycle animations - animation

I'm trying to find a way to perform animation depending of the ReactElement's lifecycle, it's pretty easy to do an animation when the component has just been mounted, but I would do another one before the component unmount.
I can't really use the ReactCSSTransitionGroup because that won't use RequestAnimationFrame.
Just to describe a bit my case, my component is a sidebar, that I can toggle on/off depending on some user's inputs.
var Sidebar = React.createClass({
componentDidMount: function() {
var menuUfeWidth = $('.menu-ufe').width();
$(this.getDOMNode()).transition({x: menuUfeWidth}, Utils.animationDuration * 2, 'snap');
},
render: function() {
return (
<div className={'leaflet-sidebar left'}>
<div className={'ufe-content'} />
</div>
);
}
});
I am wondering how would you work your way off to be able to have an animation before the component unmount.

ReactCSSTransitionGroup is just a specialized version of ReactTransitionGroup that calls componentWillEnter, componentDidEnter, componentWillLeave, and componentDidLeave based on your defined CSS.
If you don't want to use CSS animations, you can simply use ReactTransitionGroup and use a component that implements these lifecycle hooks using RAF-based animations:
<ReactTransitionGroup component="div">
<MyCustomReactTransitionComponent key={...} />
</ReactTransitionGroup>
Here's an example I found from another SO post: http://jsbin.com/jebumipimo/1/edit?html,console,output

Related

Making focus works inside a CK Editor 5 createUIElement

So I've a custom widget which renders a custom component.
conversion.for('editingDowncast').elementToElement({
model: 'modelName',
view: (modelElement, viewWriter) => {
const modelName = modelElement.getAttribute('modelName');
const modelNameView = viewWriter.createContainerElement('span', {
class: 'modelName',
'data-modelName': modelName,
});
const reactWrapper = viewWriter.createUIElement(
'span',
{
class: 'modelName__react-wrapper',
},
function (this, domDocument) {
const domElement = this.toDomElement(domDocument);
rendermodelName(modelName, domElement);
return domElement;
},
);
viewWriter.insert(
viewWriter.createPositionAt(modelNameView, 0),
reactWrapper,
);
return toWidgetEditable(modelNameView, viewWriter);
},
});
Where rendermodelName will give back a React component with a simple input box as
return (
<div>
<input type="text" />
</div>
);
https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/react.html.
But the problem is, whenever I tried to add some content inside the input, the focus is lost from the field and automatically moved to the surrounding editor. What am I missing. Tried creating a focushandler and adding the modelNameView to it.
Should I go with the new createRawElement? My current CK5 is 20.0.0 So I don't want any breaking changes coming now.
EDIT:
I researched a little bit more. seems like createRawElement may not work here. I think this doesn't have a simple solution. I tried with allowContentOf: '$block' which also not letting me focus. But these values are explicitly for normal CK widget, not for a react component.
I had the same issue and solved it by adding this tag to the parent div that wraps my Vue component.
https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/ui/widget-internals.html#exclude-dom-events-from-default-handlers
Adding from CKE Docs:
Sometimes it can be useful to prevent processing of events by default handlers, for example using React component inside an UIElement in the widget where, by default, widget itself wants to control everything. To make it possible the only thing to do is to add a data-cke-ignore-events attribute to an element or to its ancestor and then all events triggered by any of children from that element will be ignored in default handlers.
Let’s see it in an short example:
<div data-cke-ignore-events="true">
<button>Click!</button>
</div>
In the above template events dispatched from the button, which is placed inside containing data-cke-ignore-events attribute, will be ignored by default event handlers.
I faced the similar issue.
CKEditor will takes all the events on React component which you hosted on Widget.
The work around is to stop propagation of events to CKEditor which are fired from your DOM element(domElement) where your React component hosted.
Here is the sample code:
https://github.com/ckeditor/ckeditor5-core/compare/proto/input-widget#diff-44ca1561ce575490eac0d660407d5144R239
You should stop all required events. Also you can't paste any content inside the input field of React component. That will also listened by clipboardInput event of CKEditor.

Adobe Animate gotoAndPlay on mouse scroll

It's been a REALLY long time since using Flash and now have to use Adobe Animate for an HTML 5 Canvas project. I created the animation, set all the actions on the timeline to stop the timeline where I need it to be but now I need to know how to play the animation again from outside of another JS file (custom.js) inside my Animate JS file (animate.js)
I've read a ton of articles and most reference the scope of this being the problem.
Here's how I would imagine this would work.
// On scroll of div
<div onscroll="myFunction()">
// inside my custom.js
myFunction() {
this.gotoAndPlay(2);
};
Some have said to set a var of
var that=this;
And then calling that.gotoAndPlay(2);
Many thanks
Animate declares a global (window) variable exportRoot on publish that points to the root timeline.
As a demonstration, if you put this code on the root timeline:
alert(exportRoot === this);
You should see "true".
Thanks to ClayUUID
<script type="text/javascript">
function playTimeLine () {
//alert ("working");
exportRoot.gotoAndPlay(30);
}
</script>
<button onclick="playTimeLine()">PRESS</button>

react-bootstrap ModalTrigger doesn't work on React components

Looks like the ModalTrigger doesn't play well when being supplied a React component. Consider the following:
var MyDiv = React.createClass({
render : function() {
return <div>Click me!</div>
}
});
var Content = React.createClass({
render : function() {
return <div>
<ModalTrigger modal={<MyModal/>}>
<MyDiv/>
</ModalTrigger>
<ModalTrigger modal={<MyModal/>}>
<div>No, click me!</div>
</ModalTrigger>
</div>
}
});
React.render(<Content/>, document.getElementById("mydiv"));
When clicking on the first div, nothing happens, but the second div opens the modal as expected.
The DOM looks identical, but when using the React extension for Chrome I can see that there is an additional React component between the first ModalTrigger and the underlying div, named MyDiv.
The reason this is a problem is that ModalTrigger depends on its child element onClick to show the modal. When using a regular div it works as expected, but since the direct child here is a React component, there is no obvious way to make this connection go to the actual div component.
So my question, is this a shortcoming of react-bootstrap that cannot deal with the way React instantiates components, or is this the normal / expected behavior that I should work around somehow?
Thanks!
Edit:
I wanted to post this as a comment but could not format it properly :/
One way of getting around this is to have MyDiv aware that it has a this.props.onClick method, and trigger it explicitly:
var MyDiv = React.createClass({
render : function() {
return <div onClick={this.props.onClick>Click me!</div>
}
});
This creates coupling (or extra lines for PropTypes/getDefaultProps to decouple), which is far from ideal.
Another way is to wrap MyDiv in another anonymous div:
<ModalTrigger modal={<MyModal/>}>
<div><MyDiv/></div>
</ModalTrigger>
Which is much better, but somehow doesn't feel right either. Any suggestions?
It seems that the answer is under the MyDiv's responsibility, at least in how react-bootstrap works. The magic happens when the top-level div in MyDiv is passed the props, like so:
var MyDiv = React.createClass({
render : function() {
return <div {...this.props}>Click me!</div>
}
});
This is both in step with react-bootstrap's inner components' behavior, and allows MyDiv to remain agnostic of whatever is passed through. It's probably better, as Facebook suggests, to use the harmony destructuring syntax (e.g., var {myProp, ...otherProps} = this.props and then using it in <MyDiv {...otherProps}/>), but, well... harmony.

Children dynamic content with reactjs

I'm trying to experiment here. I want to build a component that auto populates some data from an ajax request after mounting. Something like this:
var AjaxComponent = React.createClass({
getInitialState: function() {
return {
data: {}
};
},
render: function() {
return (
<div>
{this.state.data.text}
</div>
);
},
componentDidMount: function() {
makeAjaxResquest(this.props.url).then(function(response){
this.setState({
data: response.body // or something
});
}.bind(this));
}
});
With that example component, I'd use <AjaxComponent url="/url/to/fetch" /> to display the content.
Now, what if I'd like to access different bits of data from children elements? Can I do something like this?
<AjaxComponent url="/url/to/fetch">
<div>
<header>{RESPONSE.title}</header>
<div>
{RESPONSE.text}
</div>
</div>
</AjaxComponent>
No problem if it doesn't render anything before the ajax request ends. The thing is how could I pass the data for children to render, not as props. Is it possible?
I had a similar scenario where I had similar Components that would query data from different APIs. Assuming you know the expected response from a given API, you could do it the same way perhaps.
Essentially make a generic Component where it props functions as an "API" of sorts, then define different types of sub components and their associated render function.
For example:
In widget, you then do something like this, where widgets is just a plain javascript file with a bunch of functions:
componentDidMount: widgets[type].componentDidMount(),
render: widgets[type].render().
In widgets, it would be like this:
var widgets = {
widget1: {
componentDidMount: function () {
//Ajax call..
},
render: function() {
//How should I draw?
}
},
widget2: //Same format, different functions
Then in some parent component you simply go
< Widget type="widget1" \>
or whatever.
There are a couple weird things about this that probably don't sit right with React. First off, you should take state all the way up to the top-level component, so I wouldn't do my ajax calls in componentDidMount...I'd more likely get the data I want for the widgets I want to render at a higher level, then pass that in as a prop too if it won't change until I make another API call (thinking Flux style flow here). Then, just pass in the data as a prop as well and just specify the render functions:
< Widget data={this.state.data[0]} type=widget1 />
The "gotcha" here is that you are making an assumption that whatever is in this data prop will match what you need in the widget type. I would pass in an object, and then validate it all in the render function etc.
That's one way. Not sure if it's valid, I'm sure someone who knows more could pick it apart but it suited my use case and I now have a library of similar components that I can selectively render by passing in data and a type, then looking up the appropriate render function and checking to make sure the data object contains everything I need to render.

Remove MouseWheel Event from dijit.form.Slider

As stated in the title i want to remove the mousewheel capability of the dijit.form.Slider since it sometimes triggers the slider when scrolling the page and the cursor hits the slider.
But it seems that the onmousewheel events are connected in the dojo source and we cannot replace or modify the dojo files.
Anyone knows a short solution (optimally a declarative one)?
Thanks
The quickest way to do this would be to clobber the _mouseWheeled method of the slider widget.
Declarative example:
<div dojoType="dijit.form.VerticalSlider" name="vertical1" id="slider2" ... >
<script type="dojo/method" event="_mouseWheeled"></script>
...
</div>
Programmatic example, single instance:
dijit.byId('mySlider')._mouseWheeled = function() {};
Programmatic, ALL instances:
dojo.extend(dijit.form.HorizontalSlider, {
_mouseWheeled: function() {}
});
(This will cover both Horizontal and Vertical sliders since VerticalSlider inherits from HorizontalSlider.)

Resources