ReactCSSTransitionGroup - how to override componentWillLeave(callback)? - javascript

I'm trying to access the componentWillMount hook in order to fade out a canvas element that is not a child of the transitioning <Home> component. (Animation of <Home> itself works as expected.)
<ReactCSSTransitionGroup transitionName="screenTrans" transitionEnterTimeout={200} transitionLeaveTimeout={3000}>
<Home key={'home'} />
</ReactCSSTransitionGroup>
Home.js:
export default class Home extends React.Component {
...
componentWillLeave( callback ) {
console.log( "am i getting called?" ) // no!
this.fadeOutCanvas();
}
}
What am I missing? Thanks...

Quite late answer but I'm now facing the same problem.
The thing is that you're using ReactCSSTransitionGroup which does NOT call the callbacks like ReactTransitionGroup (different component). The problem is that you would need a component that does both (sets css AND calls your callback)
From the docs:
When using ReactCSSTransitionGroup, there's no way for your components to be notified when a transition has ended or to perform any more complex logic around animation. If you want more fine-grained control, you can use the lower-level ReactTransitionGroup API which provides the hooks you need to do custom transitions.
Checked around and I couldn't find anything, so I'll write my own component and hopefully open source it!

Related

React: Hiding or Removing the component is more efficient?

I have three components in my app which are <Video />, <VideoPreview /> , <VideoWrapper />,
here VideoWrapper component conditionally renders other two components based on a state isDragging, whenever someone starts dragging it renders,
the code is like isDragging ? <VideoPreview /> : <Video />
Here in this question, I saw they prefer using the current (JSX short circuit rendering) approach. But in my case, the <Video /> component renders some other components, and it makes an HTTP request on every render to load the video from CDN.
So I'm confused about which one should be better, the current approach or passing the isDragging state to the video component and toggling the visibility using CSS when isDragging=true. Can anyone explain which one should be better?
You definitely want to drag the preview, and not the component itself. Depending on what you use for drag 'n drop, the dragged component could rerender multiple times during the full cycle.

Link page change not triggering animations

I am currently been for 2 days now attempting to get react-reveal to work where it does not require a refresh.
Currently what is happening is when I change page via Link it does not trigger some of the components to animate until I refresh the page.
I have read the documentation and it suggests:
refProp: string If you're using react-reveal component with a custom
React component (like a NavLink from React Router) you must specify
prop name that would be allow access to the DOM. Typically it would be
something like innerRef. By default it is ref. Optional.
So I place in my header.js
let anchorRef = React.createRef();
<Link to="/about" innerRef={anchorRef}>
Then on the about.js page I am getting undefined when I do
constructor(props) {
super(props);
console.log(props.innerRef);
}
This is what I am returning on the page as well as importing the library and etc
<Fade bottom ssrReveal distance="150px">
<p>This is an example</p>
</Fade>
All I am after doing is correctly implementing as suggested in the documents however it would seem I am missing something as I am new to using react.
This is the animation library https://www.react-reveal.com/docs/props/

Toggle state from another component

I'm pretty new to React and Redux so I may be doing this completely the wrong way, in fact judging from a few other answers to similar questions on here I suspect I'm doing quite a lot wrong.
I've got a button in my 'Layout' component which adds a class to a div, this class comes from a state. The button is a toggle and will turn the state & class on and off (this will result in making a menu appear and dimming the rest of the page).
However I also want any interaction with the 'Nav' component (which lives inside a 'Header' component which in turn lives in 'Layout') to also toggle the state & class (so clicking a link collapses the menu). In jQuery/VanillaJS this was incredibly easy but I can't seem to work out the React/Redux way of doing this.
Layout Component: https://pastebin.com/WzpbeSw7
Header Component: https://pastebin.com/c34NFtUx (probably not relevant but here for reference)
Nav Component: https://pastebin.com/EsJDuLQc
By using redux :
You can have a state like toggleBlaBla : "show" . If you connected your react component to state of redux by using react-redux , whenever you dispatch an action for changing toggleBlaBla to "hide", your connected component will rerender.
By using only react :
If you want two components to change some ui state by some events, it is a good idea to put them in a container component, so that whenever your state changes these two components rerender with your changed state passing to both components.
One way to achieve this is to do the following:
In Layout component:
On line 26 change <Header / > to: <Header handleNavClick={this.toggleNav.bind(this)} / >
In Header component:
On line 10 change <Navigation position="header" /> to: <Navigation closeNav={this.props.handleNavClick.bind(this)} position="header" />
In Navigation component:
On line 16 change return <li key={item._id}><Link to={item.slug}>{item.name}</Link></li> to: return <li key={item._id}><Link to={item.slug} onClick={this.props.closeNav.bind(this)}>{item.name}</Link></li>
Passing the props in this way will allow you to reference reference the toggleNav function inside of Layout and then will update the state accordingly.
*** Note, you may get a binding error such as React component methods may only be bound to the component instance..
If this happens, you will need to define a function on the Navigation component instead of using this.props.closeNav directly. You would need to create a function in Navigation like this: closeNav() { this.props.closeNav.bind(this) }. Don't forget to update the function on the <Link /> component to this.closeNav.bind(this)

Modify NavigationBar on route change

I can't find any documentation for how this should be done with the <Navigator/> component... Basically, when one of my scenes loads, I want to be able to, say, pass a route.navBarColor to my navigator that will automatically change the background color of the bar.
I have tried pushing a route with {navBarColor: 'red'}, etc... to renderScene(), but this does not work because renderScene() doesn't seem to have a reference to this, and when I bind(this) it, the entire scene does not render, and throws a Stack Overflow error.
Basically, I want to do something like this:
navigator.push({name: 'TestScene', navBarColor: 'transparent'})
Which then goes to
renderScene(route, navigator) {
if(route.navBarColor) {
this.setState({navBarColor: navBarColor});
} ... etc.
}
Where this.state.navBarColor is used to set the backgroundColor prop of the navigationBar.
Is this possible with the Navigator component? I see that it appears to be with NavigatorIOS, so I don't understand why it wouldn't be here.
Thanks!
The Navigator component has no display of its own, it only manages the scene transitions and routing, so asking how to do this "with Navigator" is not right. This is contrasted with NavigatorIOS which dictates the display as well.
Your question mentions "NavigationBar", is that React Native Navbar?
If yes, somewhere in the renderScene() function there will be a reference to the component, you simply need to pass it the appropriate navBarColor prop.
<NavigationBar statusBar={{ tintColor: route.navBarColor }} />

How can I get React to Replace (not Merge) VDOM?

I have a component which, in componentDidMount, gives a jQuery plugin some control over the DOM rendered by React. I know everyone says "never let anything but React touch the DOM", but hear me out, as reinventing this plugin is not feasible right now, and I think there should be an "overwrite whatever you find in the DOM" switch for React that I hope someone can point me to.
More info: I've designed it so the state of the React's DOM is entirely determined from the props given to React except while the user is dragging things around. Once dropped, I don't care how the DOM changed since the last React update, I just want to render everything from the current props of React, which I am passing in on the plugin's change handler via ReactDOM.render
The symptoms are that the nodes created by the plugin during and after dragging don't go away after React is told to update!
Yes, the nodes are key-ed initially.
The plugin is Nestable, and it adds interactivity (drag-drop reordering of the tree), and a JSBin is here: http://jsbin.com/qareki/edit?js,console,output
I'm really looking for the "Kill whatever you find" setting. I thought calling ReactDOM.render would do it, but it's clearly not doing it. Neither of course, was the more surgical setState, but I didn't expect it to. Thanks in advance for all 'you're doing-it-wrong' advice and other fixe
Manually add a div element in componentDidMount and replace it with a new one in componentDidUpdate:
class Foo extends React.Component {
render() {
// whatever HTML you want...
return (
<div>
<div>
{/* this div will contain our non-React stuff that we need to reset */}
<div ref="container"></div>
</div>
</div>);
}
blastAndRecreate() {
// throw away any content within the container and replace it with brand new content
const container = $(this.refs.container).empty();
const newDIV = $("<div>").appendTo(container);
// give this new DIV to nestable plugin
newDIV.nestable(...);
}
componentDidMount() {
this.blastAndRecreate();
}
componentDidUpdate() {
this.blastAndRecreate();
}
}

Categories