Render CPT with SSR, but don't display page until data loaded with CSR

Hi,

I’m trying to render some shortcode on my page and delay display of the page until they’re loaded. (We can treat them as any CPT though. they come from a custom plugin that creates a “shortcode” CPT)

I understand I can pass these in beforeSSR in my theme setup and this will make them available in my source…

beforeSSR: async ({ state, actions }) => {
  await Promise.all([
    actions.source.fetch("/shortcode/address/"),
    actions.source.fetch("/shortcode/telephone/")
  ]);
},

but for client-side rendering I have to do another fetch in my useEffect

this seems to work I think but feels wrong though


const data = state.source.get(state.router.link);
const post = state.source[data.type][data.id];

const addressData = state.source.get("/shortcode/address/")
const telData = state.source.get("/shortcode/telephone/")

// fetch our data client-side.. do these cause a re-render?
useEffect(() => {
  actions.source.fetch("/shortcode/address/")
  actions.source.fetch("/shortcode/telephone/")
},[])

// I thought this should be in useEffect and set address/telephone as states 
// rather than just variables, but the only way I could get the SSR working
let address, telephone, 
if(addressData?.isReady) 
   address = state.source["shortcode"][addressData.id].content.rendered
if(telData?.isReady) 
   telephone = state.source["shortcode"][telData.id].content.rendered

// Load the post, but only if the data & shortcode data is ready.
  return (data.isReady && addressData.isReady && telData.isReady) ? (

thanks for any help understanding this properly

thanks
J

Hi @codemonkeynorth

After you’ve done the fetch in beforeSSR is the content not then in the state ready for you to use?

Shortcode functions will execute server-side in WordPress and will add any content to the REST API, so the content will appear in the content.rendered property for whatever post or page contains the shortcode.

For plugins that create a CPT and add them to the REST API using "show_in_rest" => true in the args array the shortcode function is immaterial to Frontity as the data can be fetched from the CPTs endpoint - which is what it looks like you’re doing.

Can you post a link to a repo please.

Hi the above works , I was just wrapping my head around the fetch/get process and why we have the useEffect

Actually since I added the beforeSSR injection of shortcode rendered data for all routes I think that useEffect might be redundant now. Will check it again

And sorry yes just to clarify the shortcodes aren’t used in my content field. I use them to grab the content elsewhere in components that don’t render the main post content

Thanks
J

if anyone’s interested, I use this

You can add the shortcodes (specifically the rendered output) to the REST API with some custom code that I add as a plugin

// https://scottbolinger.com/custom-post-types-wp-api-v2/
function sb_add_cpts_to_api( $args, $post_type ) {

  if(is_admin()) return $args;

  if ( "shortcode" === $post_type ) {
    $args["show_in_rest"] = true;
  }
  return $args;
}
add_filter( "register_post_type_args", "sb_add_cpts_to_api", 10, 2 );

I like CCS because you can do all sorts of serverside functionality quite easily - including post loops, conditionals and dynamic args but at a basic level…

// get the content field from a post called hello-world
[content name=hello-world]

// get a custom field from a custom post type
[content type=apartment name=lux-suite-22 field=rent-per-day]

not the best examples as you can likely get the data via Frontity some other way easily enough

however for my site I’m using my own CCS shortcode [instagram_feed] - which I can grab the final rendered content from via my /shortcodes/instagram_feed/ endpoint in frontity.

This actually runs another shortcode in CCS: [global][instagram-feed num=3 cols=3 showfollow=false][/global] (Smashballoon’s Social Feed plugin)

I’m not sure how I’d pass the params to smashballoon’s shortcode via the rest API directly, so this is a simple workaround, since I don’t need to alter the params themselves

hope that’s useful to someone anyway

J

2 Likes

Actually @mburridge I still have a separate question around the original subject of the post.

I’m loading an /events page (ie has an actual Page entry in WP) which then also loads my events-archive CPT data (or alternatively I could have an events archive that then loaded content from the events page in WP)

What would be the preferred strategy for auto fetching in this case where I want both the data for the page and the archive available?

Essentially I just want to preload both sets of data when the user clicks or rolls over my “Events” menu link.

Would it be simplest to do a fetch in init() for this route? (ie both beforessr and beforecsr)

Is there any other pattern that works well?

Currently I just go to the /events page and then do a fetch on the events-archive in useEffect() and just display the Loading component again until all data isReady, before showing my whole page … however I’m having trouble working out API routes (wanted) vs browser routes (not wanted) for an archive… see below

Thanks for any suggestions
J

See also: