From beaf50b8935ee223699997ed87b8f7dc792ab6c5 Mon Sep 17 00:00:00 2001 From: Vladimir Kharlampidi Date: Wed, 3 Jun 2020 12:36:17 +0300 Subject: [PATCH] React: Use isomorphic effect + Slots --- ...lides-from-children.js => get-children.js} | 17 ++++++++++++--- src/react/swiper.js | 21 ++++++++++++------- src/react/use-isomorphic-layout-effect.js | 9 ++++++++ 3 files changed, 37 insertions(+), 10 deletions(-) rename src/react/{get-slides-from-children.js => get-children.js} (51%) create mode 100644 src/react/use-isomorphic-layout-effect.js diff --git a/src/react/get-slides-from-children.js b/src/react/get-children.js similarity index 51% rename from src/react/get-slides-from-children.js rename to src/react/get-children.js index c833d0863..a7bc32136 100644 --- a/src/react/get-slides-from-children.js +++ b/src/react/get-children.js @@ -1,7 +1,14 @@ import React from 'react'; -function getSlidesFromChildren(children) { +function getChildren(children) { const slides = []; + + const slots = { + 'container-start': [], + 'container-end': [], + 'wrapper-start': [], + 'wrapper-end': [], + }; function processChildren(c) { React.Children.toArray(c).forEach((child) => { if (child.type === React.Fragment && child.props.children) { @@ -10,11 +17,15 @@ function getSlidesFromChildren(children) { } if (child.type && child.type.displayName === 'SwiperSlide') { slides.push(child); + } else if (child.props && child.props.slot && slots[child.props.slot]) { + slots[child.props.slot].push(child); + } else { + slots['container-end'].push(child); } }); } processChildren(children); - return slides; + return { slides, slots }; } -export { getSlidesFromChildren }; +export { getChildren }; diff --git a/src/react/swiper.js b/src/react/swiper.js index aee0d92b6..e75030b8f 100644 --- a/src/react/swiper.js +++ b/src/react/swiper.js @@ -1,12 +1,13 @@ -import React, { useRef, useState, useEffect, useLayoutEffect } from 'react'; +import React, { useRef, useState, useEffect } from 'react'; import { getParams } from './get-params'; import { initSwiper } from './init-swiper'; import { needsScrollbar, needsNavigation, needsPagination, uniqueClasses } from './utils'; import { renderLoop, calcLoopedSlides } from './loop'; import { getChangedParams } from './get-changed-params'; -import { getSlidesFromChildren } from './get-slides-from-children'; +import { getChildren } from './get-children'; import { updateSwiper } from './update-swiper'; import { renderVirtual, updateOnVirtualData } from './virtual'; +import { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect'; const Swiper = ({ className, @@ -31,7 +32,7 @@ const Swiper = ({ const { params: swiperParams, passedParams, rest: restProps } = getParams(rest); - const slides = getSlidesFromChildren(children); + const { slides, slots } = getChildren(children); const changedParams = getChangedParams( passedParams, @@ -70,19 +71,19 @@ const Swiper = ({ }); // watch for params change - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (changedParams.length && swiperRef.current && !swiperRef.current.destroyed) { updateSwiper(swiperRef.current, slides, passedParams, changedParams); } }); // update on virtual update - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { updateOnVirtualData(swiperRef.current); }, [virtualData]); // init swiper - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (!swiperElRef.current) return; initSwiper( { @@ -123,6 +124,7 @@ const Swiper = ({ className={uniqueClasses(`${containerClasses}${className ? ` ${className}` : ''}`)} {...restProps} > + {slots['container-start']} {needsNavigation(swiperParams) && ( <>
@@ -131,7 +133,12 @@ const Swiper = ({ )} {needsScrollbar(swiperParams) &&
} {needsPagination(swiperParams) &&
} - {renderSlides()} + + {slots['wrapper-start']} + {renderSlides()} + {slots['wrapper-end']} + + {slots['container-end']} ); }; diff --git a/src/react/use-isomorphic-layout-effect.js b/src/react/use-isomorphic-layout-effect.js new file mode 100644 index 000000000..b1f3cd717 --- /dev/null +++ b/src/react/use-isomorphic-layout-effect.js @@ -0,0 +1,9 @@ +import { useEffect, useLayoutEffect } from 'react'; + +function useIsomorphicLayoutEffect(callback, deps) { + // eslint-disable-next-line + if (typeof window === 'undefined') return useEffect(callback, deps); + return useLayoutEffect(callback, deps); +} + +export { useIsomorphicLayoutEffect };