voronianski / react-swipe

:left_right_arrow: Swipe.js as a React component

Home Page:http://voronianski.github.io/react-swipe/demo?continuous=true

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

dynamic content for swipe

bagadim opened this issue Β· comments

Hello,
What I try to make: I have a lot of items to swipe (they can't be splited), and loading all swipe take several seconds, that is very annoying. So I decided to load 3-4 items on init, and then load others if needed while user swipe existing items.

I tried to change state on callback, it changes, but swipe component doesn't want to rerender with new state. I take a look inside react-swipe and saw script working with dom directly.

Quesiton: Is it possible to change swipe data dynamically with your component?

@bagadim I had the same issue, but then realised why. You need to add the key attribute to instruct React that the component needs re-rendering. For the value of key it's probably best to use the images.length property πŸ‘ :

<ReactSwipe key={images.length}>
    {images}
</ReactSwipe>

@Wildhoney you just made my day! Thanks

Haha β€” I remember that feeling when I discovered it was key.

Oh god thanks

thank you! just ran into the same issue!

Also ran into the issue, might be good to add @Wildhoney's solution on the README.

Opened a pull request β€” although I'm not entirely convinced my explanation is adequate. Feel free to make suggestions πŸ‘

useful questions, thanks!

When the contents (which are other react components) of one of the pages changes, is there a way to re-render only those parts? Should I use some kind of hash of the whole array as key?

I've had some success with object-hash β€” although I've noticed it doesn't support File objects β€” and probably other special objects.

import hash from 'object-hash';

// ...

{ collection.map(model => <li key={ hash(model) }> ... </li>) }

Where li could quite easily be a React component.

Thanks @Wildhoney, that indeed does the trick.

@Wildhoney: however, this re-renders everything (removes and redraws it on the actual DOM), which is not an option in our situation. Only the deepest child component which actually has a change should be re-rendered. Is this possible in some way? It seems such a trivial thing.

It would redraw li in my example – which would be your React component. If you want a change deep in your component hierarchy to be reflected in ReactSwipe then it should just work. Does your component update just fine outside of the ReactSwipe component?

That's correct: if I just render all the 'pages' without a <ReactSwipe> component 'surrounding' them, then the child component with the change does get updated.

This doesn't update (The render function of the <Platform> doesn't get called):

<ReactSwipe startSlide={startIndex} continuous={true} callback={this.onPlatformSelected} key={this.props.platforms.length}>
    {this.props.platforms.map(platform => <div key={platform.id}><Platform platform={platform} /></div>)}
</ReactSwipe>

Whereas his updates just fine:

<div>{this.props.platforms.map(platform => <div key={platform.id}><Platform platform={platform} /></div>)}</div>

Note: I somehow need the additional div around the actual Platform component/page to get the layout right. Just to make sure that this isn't causing it, I also tested without it - same issue.

Other note: using key={hash(platform)} doesn't work either - also no update.

It's because of the key on the ReactSwipe component β€” as soon as React sees that hasn't changed β€” because you're only updating an existing platform β€” then it will merrily move on without diffing the component's this.props.children.

Try hashing the array on the ReactSwipe component β€” I've not tested object-hash with an array, so I have no idea if that's possible. Then object-hash each child β€” if a key for their associated div doesn't update then the Platform component won't render β€” this should only update the Platform that has changed.

<ReactSwipe ... key={hash(platforms)}>
  {platforms.map(model => <Platform key={hash(model)} platform={model} />)}
</ReactSwipe>

Instead of only re-rendering the deepest child, that will completely redraw the entire platform - which makes sense I suppose: React thinks it's an entirely different one because it has a different key. Redrawing the entire platform isn't an option in our case because then we lose the scroll position the user was in, it'll jump back to the top.

Oh my. I've just discovered about the shouldUpdate prop, which does exactly what I need. Terribly sorry!!

That would also work! No problem. Glad you solved it.

It would be a great feature if you could add pagination to the swiper.

Hello folks! is there any way to add more items to ReactSwipe without going back to the first item?

@medJemmoudi
I need to test, but I'm pretty sure you can set swipeOption.startSlide prop to the index you currently are.

@Wildhoney you sir are the boss. Thanks a lot

commented

what can i do if i have just 6 children ,but when i change the children deep in the six children ,but it dosen't re-render?i don't want chage the key on the prop ?what the other way to re-render the ReatSwipe?