Source: list/Slider.js

import React, { useEffect, useMemo, useRef, useState } from "react";
import { Splide, SplideSlide } from '@splidejs/react-splide';
import { Template } from "../templates";
import { appActions } from "../../redux/actions";
import { connect } from "react-redux";
import { emptyObject, localStorageGetItem, localStorageSetItem } from "../../_core";

const objectPath = require("object-path");

/**
 * Componente que renderiza un Slider.
 * Para más información de como enviar el parametro options, ver la doc oficial de <a target="_blank" href="https://splidejs.com/integration/react-splide/">SplideJs</a>
 * @name Reactor.Components.List.Slider
 * @param {string} name Nombre del elemento, se usa para guardar el estado en localStorage (si se omite no recuerda la posicion del elemento seleccionado)
 * @param {string} href Nombre de la operación que va a llamar para recibir el objeto de construccion
 * @param {string} itemsNameProp Nombre de la propiedad que contendra el array de las cards (items del slider)
 * @param {string} buttonsNameProp Nombre de la propiedad dentro de cada card que contiene el objeto de contrucción del template relacionado a la card actual
 * @param {Object} options Objeto de configuración de Splide
 * @class
 * @example
<slider 
  name="Productos"
  href="HomeProductos" 
  itemsNameProp="HomeProducto"
  buttonsNameProp="HomeProductoOperaciones"
  options='{
    "autoplay": {{autoplay}},
    "interval": {{interval}},
    "pagination": {{pagination}},
    "arrows": {{arrows}},
    "type": "{{type}}"
  }'
/>
 */

const _Slider = ({ name = "splide", getAsyncContent, href, itemsnameprop, buttonsnameprop, className, autoplay, interval, pagination, arrows, type = "", rewind = "", options, ...props }) => {

  const [ state, setState ] = useState({buttons:[]});
  const [ sliderSelectIndex, setSliderSelectIndex ] = useState(0);
  const splide = useRef();

  
  useEffect(()=>{
    getAsyncContent(href, null, null)
    .then(items => {
      setState(state => ({
        ...state, 
        items: items.data.data[itemsnameprop], 
        buttons: objectPath.get((items.data.data[itemsnameprop] && items.data.data[itemsnameprop][0]) || emptyObject, buttonsnameprop)
      }));

    })
    .catch(reason => console.log(reason))
  }, [href, itemsnameprop, buttonsnameprop])
  
  useEffect(()=>{
    if(name && splide.current){
      const rememberIndex = localStorageGetItem(`slider_${name}`);
      if(rememberIndex){
        try{
          splide.current.splide.Components.Controller.go(rememberIndex*1);
        }catch(e){}
      }
    } 
  }, [state.buttons, name, splide.current])

  const handleOnMoved = (event, newIndex) => {
    if(name){
      localStorageSetItem(`slider_${name}`, newIndex)
    } 
    setState(state => ({...state, buttons: objectPath.get(state.items[newIndex], buttonsnameprop)}));
  }

  return (
    <>
      {state && state.items && 
        <>
          <Splide
            ref={splide}
            onMoved={handleOnMoved}
            options={{
              
              rewind: rewind === "true",
              type: type,
              autoplay: autoplay === "true",
              interval: interval,
              pagination: pagination === "true",
              arrows: arrows === "true",
              ...(options ? JSON.parse(options) : {})
            }}
            className={{className}}
          >
            {state.items.map( (item, index) =>
              {
                const key = Object.keys(item).find(key => key.startsWith("itemId"));
                if(!key) console.log("El item no tiene itemId!", item);
                return (
                  <SplideSlide key={(key && item[key]) || `SplideSlide${index}`}>
                    <SplideItem content={item} />
                  </SplideSlide>
                )
                  
              }
            )}
          </Splide>
          <SplideButtonsList items={state.buttons}/>
        </>
      }
    </>
  )
}

export const Slider = connect(null, appActions)(_Slider)

const SplideItem = ({content}) => {
  return <Template content={content} templateType="body" />
}

const SplideButtonsList = ({items, ...props}) => {
  return (
    <>
      {items && <Template content={items} />}
    </>
  )
}