Random post list

Hi frontity community!
I want to randomize my CPT post loop, i create an array shuffle and working fine on first load, but if i reload page i’ve got a problem, the featured image doesn’t match the title, and in console i’ve got this error:

Prop `alt` did not match. Server: "name_of_my_media" Client: "name_of_my_other_media"

That’s my code:

import React from 'react';
import {connect, styled} from 'frontity';

import FeaturedMedia from '../featured-media'
import Link from "../link";

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

    const portfolioEl = state.source.get(`/portfolio/`).items;
    const newPortfolioEl = state.source.["jetpack-portfolio"];
    const Html2React = libraries.html2react.Component
    const portfolioArray = Object.keys(portfolioEl).map((key) => portfolioEl[key]);
    const shuffledData = portfolioArray.map((a) => ({ sort: Math.random(), value: a })).sort((a, b) => a.sort - b.sort).map((a) => a.value)
    const slides = [];
    shuffledData.map(({ type, id }, index) => {
    const item = state.source[type][id];
    slides.push(item.id);
    });

    
    return(
        <HomePostWrapper>
            {slides.map((items) => {
                // console.log(newPortfolioEl[items])
                return(
                    <PortfolioCard key={items}>
                        <Link link={newPortfolioEl[items].link}>
                            <FeaturedMedia id={newPortfolioEl[items].featured_media} />
                            <h3><Html2React html={newPortfolioEl[items].title.rendered} /></h3>
                            <h5><Html2React html={newPortfolioEl[items].acf.sottotitolo} /></h5>
                        </Link>
                    </PortfolioCard>
                )
                
            })}
        </HomePostWrapper>
    )

}

export default connect(HomeTemplate);

const HomePostWrapper = styled.div`
    display: flex;
    flex-wrap:wrap;
    align-items:top;
`;

const PortfolioCard = styled.div`
    width:33%
`;

Can someone help me?
Thankyou so much :slight_smile:

Hi @matteo.lcd

TBH I’m having a bit of difficulty trying to figure out what is going on here, esp without being able to see the structure of your data. It would be easier and more convenient to figure out what’s happening at each stage if I can clone your repo and access your data.

Can you provide a link to a repo please, and ensure that your data source is publicly available. This will enable both myself and others to be able to help you. Please see here for the kind of information about your issue that it’s useful to provide.

@mburridge if there’s a server/client mismatch error, presumably this is because the randomization is breaking the hydration process? I believe frontity does a server & client render conciliation and those 2 things should match?

if that’s the case it’s an interesting conundrum because the only way would be to return all items and then take a random selection, rather than doing a randomized query on the backend (since the randomization would not be the same on both server and client)

however returning all items on the API would presumably be far from optimal?

I believe @codemonkeynorth has a good point, for several reasons.

The server and client will both have different data since they both het a different list of random items, which will cause issues.

Second; it may a take a bit of PHP work to create a custom API endpoint, but performance wise it’s a lot better to have it limited and randomized at the server already. And I would ever advice you to do it at SQL level and not in PHP. So limit and randomize the results in the SQL query and return that in the REST API call.

Hi everyone! I’m not able to test until Tuesday, but maybe based on your suggestions this might be a good solution:

This article show how to randomize the post or custom post type post’s rest Api from wordpress php code, i think it’s a good solution, but i need to try first.

I keep you updated!
:slight_smile:

@Johan @mburridge @codemonkeynorth
Solution found!
I use “useeffect” before my component, now i’m able to shuffle my cpt posts array!

This is the code:

import React , { useEffect, useState } from 'react';
import {connect, styled} from 'frontity';
import HomeCard from './home-card';

const HomeTemplate = ({state, libraries, actions}) => {

    useEffect((link) => {
        // actions.source.fetch("/portfolio");
        const dataPost = state.source.get("/portfolio");
        const postArray = dataPost.items.sort(() => Math.random() - 0.5);
        const portfolioPosts = state.source.data[link];
        
        Object.assign(portfolioPosts, {
            items: postArray,
            isRandom: true,
          });

        //   console.log('POSTDATAMENU',state.source)
      }, []);

    const portfolioEl = state.source.get(`/portfolio/`).items;
    const Html2React = libraries.html2react.Component

    // const data = state.source.get(state.router.link)
    // console.log('portfolioel',portfolioEl);
    // console.log('mydata',state.source.data);
    // console.log('portdata',state.source.get(`/portfolio/`).items);
    // console.log(portfolioEl);
    


    return(
        <HomePostWrapper>
            {portfolioEl.map((singlePort) => {
                const portfolioPost = state.source[singlePort.type][singlePort.id];
                return(
                    <HomeCard key={singlePort.id} cardElement={portfolioPost} />
                )
            })}
            {console.log(state)}
        </HomePostWrapper>
    )

}

export default connect(HomeTemplate);

const HomePostWrapper = styled.div`
    display: flex;
    flex-wrap:wrap;
    align-items:top;
`;

It’s not a very clean code, but I hope it’s useful for everyone!
:sunglasses: :sunglasses: :sunglasses:

2 Likes