HowTo? Pure React Carousel

HEY!

Cool thing I’m having trouble implementing and have no idea on how to approach this so ideas appreciated.

I’m using Pure React Carousel to add a swipeable carousel of “testimonials” of guests for a property management website.

Here is the branch that’s deployed. As you can see, my testimonials component is on the very bottom: https://guestrealty-o0bjkqfx6.vercel.app/

Here is the branch its deployed to: Github Repo

In the Carousel documentation, to implement it seems all you have to do is the following:

import React from 'react';
import { CarouselProvider, Slider, Slide, ButtonBack, ButtonNext } from 'pure-react-carousel';
import 'pure-react-carousel/dist/react-carousel.es.css';
 
export default class extends React.Component {
  render() {
    return (
      <CarouselProvider
        naturalSlideWidth={100}
        naturalSlideHeight={125}
        totalSlides={3}
      >
        <Slider>
          <Slide index={0}>I am the first Slide.</Slide>
          <Slide index={1}>I am the second Slide.</Slide>
          <Slide index={2}>I am the third Slide.</Slide>
        </Slider>
      </CarouselProvider>
    );
  }
}

So my thinking was to use a preprocessor to format the div’s of blockquote Gutenberg blog to format like a div above, then pull it into my testimonials component using HTML to react. I know that’s probably not the right way of doing it, but what I’m trying to achieve is the above code with how I implemented it below:

my Testimonials component:

import React from "react";
import { connect, styled } from "frontity"
import { CarouselProvider, Slider, Slide, ButtonBack, ButtonNext } from 'pure-react-carousel';
import 'pure-react-carousel/dist/react-carousel.es.css';

const Testimonial = ({ state, libraries }) => {

    const data = state.source.get("/testimonials");
    const quotes = state.source.page[data.id];
    const Html2React = libraries.html2react.Component;

      return (
        <ContactContainer>
            <CarouselProvider
                naturalSlideWidth={100}
                naturalSlideHeight={125}
                totalSlides={4}
            >
                <Slider>
                    
                <Html2React html={quotes.content.rendered} />
                </Slider>
                <ButtonBack>Back</ButtonBack>
                <ButtonNext>Next</ButtonNext>
            </CarouselProvider>
        </ContactContainer>
    );
};

export default connect(Testimonial);

const ContactContainer = styled.div`
    padding: 5px;
`

my quotes preprocessor:

import React from 'react';
import { styled } from "frontity";

const Quote = ({ quote, author}) => {
    console.log('Quote')
    console.log({ quote, author})
    return (
        <Container>
            <Blockquote>
                <h3>" {quote} "</h3>
                <h4>- {author} </h4>
            </Blockquote>
        </Container>
    )
}

const quote = {
    name: 'quote',
    priority: 20,
    test: ({ component, props }) => component === "blockquote" && props.className === "wp-block-quote",
    processor: ({ node }) => {
        const quote = node.children[0].children[0].content
        const author = node.children[1].children[0].content
        return{
            component: Quote,
            props: { quote, author}
        }
    },
}

export default quote;

const Container = styled.div`
    background: #f6f2ec;
`

const Blockquote = styled.div`
    background: #153211;
    border: 2px solid #ccb25c;
    border-radius: 25px;
    padding: 10px;
    margin: 10px;
    h3{
        color: #ccb25c;
        font-weight: 800;
        font-style: italic;
        font-size: 2rem;
    }
    h4{
        color: #f6f2ec; 
    }
`

How can I break up the HTML into separate divs that are rendered in HTML to react to become separate divs to make this carousel usable?

Currently, it seems that when I render the HTML, it renders the 4 divs generated from my quotes preprocessor as one giant div (which is why my slider only thinks there is only one slide?). I’m trying to make each blockquote in the green boxes as its own slide.

Hi!

As you can See in this quote, the slider/carousel you use needs this structure.

Your actual code doesn’t use this required schema above.

You need to wrap each slide item with the <Slide>...</Slide> container.
See: https://www.npmjs.com/package/pure-react-carousel#slide-

One option is to map your content Items.

qoutes.map((qoute, i) => (
    <Slide key={i} index={i}>
        <Html2React html={quote.content.rendered} />
    </Slide>
));

Something like this should work inside the <Slider>...</Slider> Container.
I don’t know the structure of your data, so you eventually need to adjust the js map.

And i would recommend you to dynamically set the totalSlides instead of setting this property static.
Because this value need to match with the real count of slides.
Something like totalSlides={quotes.length} should work.

Kind regards
Chris

3 Likes

@Chris1337 I totally didn’t even think to map.

My next question is how do I format this to reach the children of content by each blockquote? I tried implementing a map and got the famous array.map is not a function error =(.

This is how my data structure is coming in from content.rendered:

"
    <blockquote class="wp-block-quote"><p>I love this</p><cite>Test user 1, Property Owner</cite></blockquote>
    <blockquote class="wp-block-quote"><p>I love this also</p><cite>Test User 2</cite></blockquote>
    <blockquote class="wp-block-quote"><p>I also love this. Great job!</p><cite>Test User 3, Guest at 33 Bronte</cite></blockquote>
    <blockquote class="wp-block-quote"><p>This is the best comment ever</p><cite>Happy Renter, Aus</cite></blockquote>
"

And what I have now:

const Testimonial = ({ state, libraries }) => {
    const data = state.source.get("/testimonials");
    const quotes = state.source.page[data.id];
    const Html2React = libraries.html2react.Component;
      return (
        <ContactContainer>
            <CarouselProvider
                naturalSlideWidth={100}
                naturalSlideHeight={125}
                totalSlides={quotes.length}
            >
            <Slider>
            {quotes.map((quote, i) => (
                <Slide key={quote} index={i}>
                    <Html2React html={quote.content.rendered} />
                </Slide>
            ))}
            </Slider>
            <ButtonBack>Back</ButtonBack>
            <ButtonNext>Next</ButtonNext>
            </CarouselProvider>
        </ContactContainer>
    );
};

Hey @chayce.solchaga,

if you log quotes and quotes.content, what is the output?

console.log(quotes);
console.log(quotes.content);

Kind regards
Chris

@Chris1337
First of all, thank you for all the help! I truly appreciate it.

When I console.log the following this is what happens:
console.log(quotes) - in the testimonial component:

 {quotes: Proxy}
quotes: Proxy
[[Handler]]: Object
[[Target]]: Object
acf: []
author: 1
comment_status: "closed"
content:
protected: false
rendered: "↵<blockquote class="wp-block-quote"><p>I love this</p><cite>Test user 1, Property Owner</cite></blockquote>↵↵↵↵<blockquote class="wp-block-quote"><p>I love this also</p><cite>Test User 2</cite></blockquote>↵↵↵↵<blockquote class="wp-block-quote"><p>I also love this. Great job!</p><cite>Test User 3, Guest at 33 Bronte</cite></blockquote>↵↵↵↵<blockquote class="wp-block-quote"><p>This is the best comment ever</p><cite>Happy Renter, Aus</cite></blockquote>↵"
__proto__:
constructor: Ć’ Object()
hasOwnProperty: Ć’ hasOwnProperty()
isPrototypeOf: Ć’ isPrototypeOf()
propertyIsEnumerable: Ć’ propertyIsEnumerable()
toLocaleString: Ć’ toLocaleString()
toString: Ć’ toString()
valueOf: Ć’ valueOf()
__defineGetter__: Ć’ __defineGetter__()
__defineSetter__: Ć’ __defineSetter__()
__lookupGetter__: Ć’ __lookupGetter__()
__lookupSetter__: Ć’ __lookupSetter__()
get __proto__: Ć’ __proto__()
set __proto__: Ć’ __proto__()
date: "2020-10-27T00:04:43"
date_gmt: "2020-10-27T00:04:43"
excerpt: {rendered: "<p>I love this Test user 1, Property Owner I love …s is the best comment ever Happy Renter, Aus</p>↵", protected: false}
featured_media: 0
guid: {rendered: "https://guestrealty.co/?page_id=305"}
id: 305
link: "/testimonials/"
menu_order: 0
meta: []
modified: "2020-10-27T01:42:59"
modified_gmt: "2020-10-27T01:42:59"
parent: 0
ping_status: "closed"
slug: "testimonials"
status: "publish"
template: ""
title: {rendered: "Testimonials"}
type: "page"
_embedded: {author: Array(1)}
_links: {self: Array(1), collection: Array(1), about: Array(1), author: Array(1), replies: Array(1), …}
__proto__: Object
[[IsRevoked]]: false
__proto__: Object

When I console.log quotes.content - it throws an error.

When I am inside of my quotes processor, I am console.logging quote and it returns the quote and author as specified from what I defined as quote in quotes:

import React from 'react';
import { styled } from "frontity";
import { Slide } from 'pure-react-carousel';
import 'pure-react-carousel/dist/react-carousel.es.css';

const Quote = ({ quote, author}) => {
// Console.log's quote and author
    console.log('Quote')
    console.log({ quote, author})
    return (
        <Slide>  
            <Blockquote>
                <h3>" {quote} "</h3>
                <h4>- {author} </h4>
            </Blockquote>
        </Slide>
        
    )
}

const quote = {
    name: 'quote',
    priority: 20,
    test: ({ component, props }) => component === "blockquote" && props.className === "wp-block-quote",
    processor: ({ node }) => {
// Where I defined quote and author
        const quote = node.children[0].children[0].content
        const author = node.children[1].children[0].content
        return{
            component: Quote,
            props: { quote, author}
        }
    },
}

export default quote;

and resulting console.log:

Quote
{quote: "I love this", author: "Test user 1, Property Owner"}
author: "Test user 1, Property Owner"
quote: "I love this"
__proto__: Object
Quote
{quote: "I love this also", author: "Test User 2"}
author: "Test User 2"
quote: "I love this also"
__proto__: Object
Quote
{quote: "I also love this. Great job!", author: "Test User 3, Guest at 33 Bronte"}
author: "Test User 3, Guest at 33 Bronte"
quote: "I also love this. Great job!"
__proto__: Object
Quote
{quote: "This is the best comment ever", author: "Happy Renter, Aus"}
author: "Happy Renter, Aus"
quote: "This is the best comment ever"
__proto__: Object

Hey @chayce.solchaga

didn’t know you actually use a processor for the quotes.
With the <Slide> inside your processor you should be fine with rendering your quotes.

<Slider>                    
    <Html2React html={quotes.content.rendered} />
</Slider>

At least as long as <Html2React /> don’t create an additional div container around your quotes.
If so, you need to have an option to remove that div created by <Html2React />.
But i actually don’t know.

Kind regards
Chris

1 Like

Hey @Chris1337

Never ended up making that work for my testimonials, but I did get it to work for a different component - my custom post type archive where users can swipe through the different properties.

I still had some trouble styling buttons in it so I just decided to put text to have users swipe but other than that happy with what I have. In the future if I could do this website over again, I would’ve probably worked with processors from the beginning - I think it would’ve made building this carousel much simpler.

Here’s a link to show that carousels can work if you scroll all the way to the bottom of the page: https://guestrealty-7fygbb34u.vercel.app/sub/property-owners/

Once I finish my portfolio site, and implement a slider taking my previous experience from this site, I’ll post a tutorial so that way people can understand on how things should be set up on Wordpress and the Frontity side so its easier to understand some of the gotchas.