Bridging the Gap: Drupal and React Synergy
For some time now, I've been working on Headless cms configuration with Drupal and React. While both are powerful tools on their own, combining them can unlock a new level of performance and user experience.
PS -
So here's what I have achieved:
I was able to move data from Drupal to React more quickly and easily than I could have with an API—yes, a headless CMS which lacks an API.
(Only when react.js is loaded on the web by the Drupal host; cross-origin react.js still requires api's.)
How did I do that ?
So in summary - I implemented the drupalSettings concept on my own rather than attaching data to drupalSettings and utilised it to provide data to react.
What's Drupal Setting ?
When we view any page on Drupal, JSON data is rendered on the HTML document that we receive.
Something like this.
And drupal’s own javascript parses that json into an Global variable called drupalSettings.
So back to our case, we want to access a nodes data in our react code, well I managed to get all the data in a JSON format.
Parsed it as a Javscript object
Recommended by LinkedIn
How to implement it in your code ?
It goes back to Oct 2021 when drupal introduced something called a Bundle class which essentially lets you change the class of the bundle with something called hook_core_entity_bundle_info_alter()
use Drupal\mymodule\Entity\BasicPage;
function mymodule_entity_bundle_info_alter(array &$bundles): void {
if (isset($bundles['node']['page'])) {
$bundles['node']['page']['class'] = BasicPage::class;
}
}
Something like this .
You can read bundle class documentation over here Bundle Class.
Now for each of the paragraph bundle you can have your custom logic
<?php
namespace Drupal\monstoic_core\ParagraphPreprocessor;
use Drupal\paragraphs\Entity\Paragraph;
use Drupal\monstoic_event_processor\Utility\Utility;
class OurRole extends Paragraph
{
public function getData()
{
$result = [
'field_our_role_description' => $this->get('field_our_role_description')->value,
'field_our_role_title' => $this->get('field_our_role_title')->value,
'field_background' => Utility::resolveMedia($this->get('field_background')->referencedEntities()[0]),
];
//$json = json_encode($result);
return $result;
}
}
Something like this.
And because now you have set this as your bundle class for the paragraph our_role.
$bundles["node"]["homepage"]["class"] = Homepage::class;
$bundles["paragraph"]["our_role"]["class"] = OurRole::class;
(*Note that we also have overridden the node bundle.)
You should technically be able to use this getData() function inside the paragraph twig.
<script type="application/json" data-paragraph-selector="our_role">
{{ paragraph.getData()|raw }}
</script>
Yes you can and it works just fine.
Now the problem is I want whole homepage inside the JSON, well as we already have overridden the Homepage node bundle so let's check that code now,
<?php
namespace Drupal\monstoic_core\NodePreprocessor;
use Drupal\monstoic_event_processor\Utility\Utility;
use Drupal\node\Entity\Node;
class Homepage extends Node
{
public function getData()
{
$result = [
"field_home_page_hero" => $this->get("field_home_page_hero")->referencedEntities()[0]->getData(),
"field_our_process" => $this->get("field_our_process")->referencedEntities()[0]->getData(),
"field_our_role" => $this->get("field_our_role")->referencedEntities()[0]->getData(),
"field_our_service_section" => $this->get("field_our_service_section")->referencedEntities()[0]->getData(),
"field_our_turnaround_time" => $this->get("field_our_turnaround_time")->referencedEntities()[0]->getData(),
"field_trusted_partners_section" => $this->get("field_trusted_partners_section")->referencedEntities()[0]->getData(),
];
$json = json_encode($result);
return $json;
}
}
Here as you can see we have called the getData() function in the referencedEntity of “field_our_role” which is essentially the bundle our_role, so we get that data and we render this whole stuff as a json in the node twig.
<script type="application/json" data-node-selector="homepage">
{{ node.getData()|raw }}
</script>
Thanks for spending time reading it.