Skip to content

Commit 13bb643

Browse files
committed
feat(SimpleViewSlider): add keepPrecedingViewsMounted prop
1 parent f027b19 commit 13bb643

File tree

4 files changed

+121
-9
lines changed

4 files changed

+121
-9
lines changed

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,10 @@ ReactDOM.render(
180180
document.getElementById('root')
181181
)
182182
```
183+
184+
### Additional props
185+
186+
##### `keepPrecedingViewsMounted: boolean` (default: `false`)
187+
188+
If `true`, `SimpleViewSlider` will keep views preceding the active view mounted, but not views following the active view.
189+
(As mentioned above, the order is determined by the `children`'s `key`s.)

src/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,9 @@ export default class ViewSlider extends React.Component<Props, State> {
318318

319319
const finalViewportStyle = {
320320
position: 'relative',
321-
transform: `translateX(${activeView * spacing * (rtl ? 100 : -100)}%)`,
321+
transform: `translateX(calc(${activeView *
322+
spacing *
323+
(rtl ? 100 : -100)}% + 0px))`,
322324
whiteSpace: 'nowrap',
323325
minHeight: '100%',
324326
direction: rtl ? 'rtl' : 'ltr',

src/simple.js

+13-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { Props as ViewSliderProps, ViewProps } from './index'
99
export type Props = {
1010
children?: any,
1111
keepViewsMounted?: ?boolean,
12+
keepPrecedingViewsMounted?: ?boolean,
1213
animateHeight?: ?boolean,
1314
transitionDuration?: ?number,
1415
transitionTimingFunction?: ?string,
@@ -48,10 +49,7 @@ export function createSimpleViewSlider(
4849
const activeView = parseInt(child.key)
4950
const views = []
5051
views[activeView] = child
51-
this.state = {
52-
views,
53-
activeView,
54-
}
52+
this.state = { views, activeView }
5553
}
5654

5755
componentDidUpdate(prevProps: Props) {
@@ -60,10 +58,14 @@ export function createSimpleViewSlider(
6058
const activeView = parseInt(child.key)
6159
const views = [...this.state.views]
6260
views[activeView] = child
63-
this.setState({
64-
views,
65-
activeView,
66-
})
61+
if (!this.props.keepViewsMounted) {
62+
views.length = Math.min(views.length, activeView + 1)
63+
}
64+
this.setState({ views, activeView })
65+
} else if (prevProps.keepViewsMounted && !this.props.keepViewsMounted) {
66+
const views = [...this.state.views]
67+
views.length = Math.min(views.length, this.state.activeView + 1)
68+
this.setState({ views })
6769
}
6870
}
6971

@@ -75,12 +77,15 @@ export function createSimpleViewSlider(
7577
// Flow's React.ComponentType + defaultProps is foobar...
7678
spacing,
7779
rtl,
80+
keepViewsMounted,
81+
keepPrecedingViewsMounted,
7882
...props
7983
} = this.props
8084
const { activeView, views } = this.state
8185
return (
8286
<ViewSlider
8387
{...props}
88+
keepViewsMounted={keepViewsMounted || keepPrecedingViewsMounted}
8489
spacing={(spacing: any)}
8590
rtl={(rtl: any)}
8691
renderView={this.renderView}

test/index.js

+98
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,104 @@ describe('SimpleViewSlider', () => {
157157
clock.tick(1000)
158158
expect(comp.text()).to.equal('Child 1')
159159

160+
comp.unmount()
161+
})
162+
it('keepViewsMounted works', () => {
163+
const comp = mount(
164+
<SimpleViewSlider keepViewsMounted>
165+
<div key={0}>Child 0</div>
166+
</SimpleViewSlider>
167+
)
168+
169+
expect(comp.text()).to.equal('Child 0')
170+
171+
comp.setProps({
172+
children: <div key={1}>Child 1</div>,
173+
})
174+
175+
clock.tick(1000)
176+
expect(comp.update().text()).to.equal('Child 0Child 1')
177+
178+
comp.setProps({
179+
children: <div key={2}>Child 2</div>,
180+
})
181+
182+
clock.tick(1000)
183+
expect(comp.update().text()).to.equal('Child 0Child 1Child 2')
184+
185+
comp.setProps({
186+
children: <div key={1}>Child a</div>,
187+
})
188+
189+
clock.tick(1000)
190+
expect(comp.update().text()).to.equal('Child 0Child aChild 2')
191+
192+
comp.unmount()
193+
})
194+
it('keepPrecedingViewsMounted works', () => {
195+
const comp = mount(
196+
<SimpleViewSlider keepPrecedingViewsMounted>
197+
<div key={0}>Child 0</div>
198+
</SimpleViewSlider>
199+
)
200+
201+
expect(comp.text()).to.equal('Child 0')
202+
203+
comp.setProps({
204+
children: <div key={1}>Child 1</div>,
205+
})
206+
207+
clock.tick(1000)
208+
expect(comp.update().text()).to.equal('Child 0Child 1')
209+
210+
comp.setProps({
211+
children: <div key={2}>Child 2</div>,
212+
})
213+
214+
clock.tick(1000)
215+
expect(comp.update().text()).to.equal('Child 0Child 1Child 2')
216+
217+
comp.setProps({
218+
children: <div key={1}>Child a</div>,
219+
})
220+
221+
clock.tick(1000)
222+
expect(comp.update().text()).to.equal('Child 0Child a')
223+
224+
comp.unmount()
225+
})
226+
it('changing keepPrecedingViewsMounted works', () => {
227+
const comp = mount(
228+
<SimpleViewSlider keepViewsMounted>
229+
<div key={0}>Child 0</div>
230+
</SimpleViewSlider>
231+
)
232+
233+
expect(comp.text()).to.equal('Child 0')
234+
235+
comp.setProps({
236+
children: <div key={1}>Child 1</div>,
237+
})
238+
239+
clock.tick(1000)
240+
expect(comp.update().text()).to.equal('Child 0Child 1')
241+
242+
comp.setProps({
243+
children: <div key={2}>Child 2</div>,
244+
})
245+
246+
clock.tick(1000)
247+
expect(comp.update().text()).to.equal('Child 0Child 1Child 2')
248+
249+
comp.setProps({
250+
keepViewsMounted: false,
251+
keepPrecedingViewsMounted: true,
252+
children: <div key={1}>Child a</div>,
253+
})
254+
255+
clock.tick(1000)
256+
expect(comp.update().text()).to.equal('Child 0Child a')
257+
160258
comp.unmount()
161259
})
162260
})

0 commit comments

Comments
 (0)