react-transition-group conditionally animate out - reactjs

I'm trying to use react-transition-group to add some animation to a list that I have.
This is my general setup, I have list component that renders a number of children. There are a number of interactions that cause items to be added/removed from this list. Some of these actions need to cause the component to be removed using an animation but I can't seem to get that working and I'm guessing maybe I'm missing something here.
This is my basic setup:
<TransitionGroup className="list" component="ul">
{this.props.item.map(item => (
<CSSTransition key={item.id} timeout={500} classNames="fade" enter={false} exit={!!item.shouldAnimate}>
<ChildComponent/>
</CSSTransition>
))}
</TransitionGroup>
I have verified that everything is fine in my state logic (i.e. shouldAnimate is set to true as I expect but it still doesn't animate.
Any suggestions?
Edit:
Created a fiddle showing the problem and I think I now see the issue.
http://jsfiddle.net/af0ee2eo/2/
As I described above I don't know until the user takes an action if that action should be one that causes the item to be animated or not when it is removed from the list. I'm setting shouldAnimate correctly but then before the next render I'm removing that item from the list. If I delay the removal until after the next render things work okay but that's annoying to have to do every time (this is what I am demonstrating by the "Use Delay?" checkbox at the bottom of the fiddle). I wish there was a way to inject state into the state of the item held by TransitionGroup's component state.
If anyone has any other idea how I might fix this without a setTimeout or requestAnimationFrame render hack let me know otherwise I'll just mark this question as answered.

I've figured it out and just in case someone else comes along and see this the answer is to use the childFactory prop. It allows you to change prop values on leaving children.
Link with more info: https://medium.com/lalilo/dynamic-transitions-with-react-router-and-react-transition-group-69ab795815c9

Related

React dynamically rendered component not updating

I'm trying to render a list of components using map function in render. When I change state, render function is called as expected but my component is not updated.
I've made a sample codesandbox here
https://codesandbox.io/s/nk24mr55om
What am I doing wrong?
I've added some console logs and it look like secret content should be displayed but it is not
Once your item is pushed into the items array, it will not be updated, ever. A solution to this would be to convert the items you push into arrow functions that will get a show parameter :
items.push(show =>
<div>
{show && <div>I'm secret</div>}
My content
<br />
<input
type="button"
onClick={showSecret}
value="Show secret content"
/>
</div>
);
And then call it in the mapping of your render :
return <div key={index}>{item(show)}</div>;
However, with this solution, clicking on one button will cause every item to show their secret element, if this isn't the behavior you expect and want every item to act on its own, I suggest creating a hook for each item. And ahev them store their own show variable in their state.
I have no experience yet with react hooks, but i tried to understand whats going on.
The variable items you refer to is neither a prop nor in the state of your component, i would make the component stateful and initialize items in the state.
Maybe there is a better way with react hooks that someone else can give

Real-Time use case of this.props.children

I have read many articles to find out the real time use case of this.props.children but i didn't find the answer that i am looking for.I know that this.props.children is used to access the data b/w the opening and closing tag of a component. But my question is why can't we add a prop to the component instead of writing data b/w opening and closing tag.
for Ex:
<Example>This is data<Example> //can be accessed as this.props.children
can be written as
<Example data="This is data"/> //can be accessed as this.props.data
Can somebody please explain me with a real-time example of where we can achieve a certain task by using only this.props.children?
For example if you have complicated children of a component:
<Card>
<div class='title'>Title</div>
<div class='content'>Content</div>
</Card>
It would be easier than if you write like:
<Card content={[<div class='title'>Title</div>, <....>]} />
Samething you can find here, for example in Drawer component of Material-UI here. Drawer is a component that slides from the left, it can contain anything, so using props.childrens.
While making an app, you want a parent component which will render anything in your component. The use cases which I can think of are:
When you want to open a different component depending upon the route change.
const App = ({ children }) => (
<div className="full-height">
{children}
</div>
);
When you want to have same styles throughout your app for generic elements such as body, head etc. You'll just have to apply on this component, e.g., in above example, the full-height will get applied everywhere in the app on top component. (Obviously there are other work arounds but this is always more clear)
For use cases where you want to expose your component (when component doesn't know children ahead of time) as libraries and props can vary a lot and complicates the rendering. Read this
Obviously you don't have to use it but it makes code more elegant and understandable.

Does React have keep-alive like Vue js?

I made a Todo list with React js. This web has List and Detail pages.
There is a list and 1 list has 10 items. When user scroll bottom, next page data will be loaded.
user click 40th item -> watch detail page (react-router) -> click back button
The main page scroll top of the page and get 1st page data again.
How to restore scroll position and datas without Ajax call?
When I used Vue js, i’ve used 'keep-alive' element.
Help me. Thank you :)
If you are working with react-router
Component can not be cached while going forward or back which lead to losing data and interaction while using Route
Component would be unmounted when Route was unmatched
After reading source code of Route we found that using children prop as a function could help to control rendering behavior.
Hiding instead of Removing would fix this issue.
I am already fixed it with my tools react-router-cache-route
Usage
Replace <Route> with <CacheRoute>
Replace <Switch> with <CacheSwitch>
If you want real <KeepAlive /> for React
I have my implementation react-activation
Online Demo
Usage
import KeepAlive, { AliveScope } from 'react-activation'
function App() {
const [show, setShow] = useState(true)
return (
<AliveScope>
<button onClick={() => setShow(show => !show)}>Toggle</button>
{show && (
<KeepAlive>
<Test />
</KeepAlive>
)}
</AliveScope>
)
}
The implementation principle is easy to say.
Because React will unload components that are in the intrinsic component hierarchy, we need to extract the components in <KeepAlive>, that is, their children props, and render them into a component that will not be unloaded.
Until now the awnser is no unfortunately. But there's a issue about it in React repository: https://github.com/facebook/react/issues/12039
keep-alive is really nice. Generally, if you want to preserve state, you look at using a Flux (Redux lib) design pattern to store your data in a global store. You can even add this to a single component use case and not use it anywhere else if you wish.
If you need to keep the component around you can look at hoisting the component up and adding a "display: none" style to the component there. This will preserve the Node and thus the component state along with it.
Worth noting also is the "key" field helps the React engine figure out what tree should be unmounted and what should be kept. If you have the same component and want to preserve its state across multiple usages, maintain the key value. Conversely, if you want to ensure an unmount, just change the key value.
While searching for the same, I found this library, which is said to be doing the same. Have not used though - https://www.npmjs.com/package/react-keep-alive

React-Router v4 (List / ListItem, Routes, Animations)

I just ran into a problem with react router v4, maybe it's not a big deal, but I don't know how to handle this the right way.
It should look something like this:
<Route path="/" component={List}>
<Route path="/listitem/:id" component={ListItem} />
</Route>
If I am now on the ("/" - List)-page I want to see all the ListItems from the different ("/listitem/:id" - ListItem)-pages. (with less informations but this should be a simple css-problem)
As soon as I click at one, I want to turn that one fullscreen (animations and stuff... but that's not the problem here) and the route should change, unsurprisingly :-).
If I am now on one specific ListItem and trigger history.goBack(), I want to animate that Item back into the List and the route should change back to "/".
Additional (maybe optional) thought: If I visite the site initially at a "/listitem/:id"-page and click on a Link to the "(/" - List)-page, there shouldn't be any animation of the ListItem.
I guess it's a basic problem for react-router, but I actually don't know right now how to implement this properly.
I don't know if it makes any difference, but I am using Redux aswell.
I hope, someone can help me out.
Thank you in advance.
I think this would be best handled with state in the Parent component. For example:
this.state = {
fullscreen: false,
idOpened: null
}
Once you click on the child component (the list item), you set a callback that sends the ID to the parent which then triggers the fullscreen-mode. This way you won't need to use the history API and the visitors won't have to wait for page loads (except for the initial one).
It'll also make it easy to not trigger any animations when clicking on another list item.

Rendering null in react element prevents me from using css's :empty selector

To better explain my question, I'll use an example:
Let's say I have two react elements, which contain one another. Lets call the container Box, and the child Stuff. Box just renders a div with className="box" which surrounds the children it is given. Stuff most of the time renders something, but its render function can return null when it decides there's nothing to render.
Here's the twist: if <Box> is empty, I don't want to show it at all. So I decided to use css3 selectors, and write something like
.box:empty {
display: none;
}
... which should work, except react renders a <noscript> tag, which prevents the browser from treating the parent .box element as empty...
Is there an elegant way around this? I'd like to keep the logic of determining emptiness inside of Stuff, and have Box just "look" at its contents and decide whether it wants to show anything or not.
UPDATE
This fiddle https://jsfiddle.net/69z2wepo/67543/ has an example of what I'm trying to do. Strangely, in that fiddle, it works, and react doesn't render <noscript> tags... why does it render <noscript>s in my code? In what cases does react choose to render <noscript>s?
Found the problem!
I was using an old version of react-css-modules (3.7.7). Upgrading to 4.1.0 fixed it.
Looks like this was a relatively recent fix, too:
https://github.com/gajus/react-css-modules/commit/a9c8de252d5464037090e155c431abfe9f671531

Resources