Loosely Coupled: Pass data to React app via drupalSettings

29 / Dec / 2022 by Deepali Agarwal 0 comments

There may be a need to pass a variable, checkbox settings, or some global settings from drupal to react. This can be achieved by passing data from drupal into an API and consuming the same API in react. But why call an extra API when we can achieve it without it?
We will be using #attached/drupalSettings to accomplish this.

Step 1: Modify our library definition.

Add dependency for drupalSettings where react bundle file is included:

react-lib:
  version: 1.x
  js:
    js/react-app/dist/app.bundle.js: { minified: true }
  dependencies:
    - core/drupalSettings

Step 2: Pass settings to the browser using the #attached framework.

This can be done either in following ways:

i) Any Preprocess hook:

function react_module_preprocess_node(&$variables) {
  $variables['content']['#attached']['drupalSettings']['reactApp']['setting1'] = 'value1';
  $variables['content']['#attached']['drupalSettings']['reactApp']['setting2'] = 'value2';
}

ii) Page attachment hook:

function react_module_page_attachments(array &$attachments) {
  $attachments['#attached']['library'][] = 'react_module/react-lib';
  $attachments['#attached']['drupalSettings']['reactApp']['setting1'] = 'value1';
  $attachments['#attached']['drupalSettings']['reactApp']['setting2'] = 'value2';
}

iii) Render array (Forms, Block etc).

For Instance, if you want to do things from a form alter, where we have added the markup and the library:

$form['my_react_app'] = [
  '#markup' => '<div id="react-root"></div>',
  '#attached' => [
    'library' => [
      'react_module/react-lib'
    ],
    'drupalSettings' => [
      'reactApp' => [
        'setting1' => 'value1',
        'setting2' => 'value2',
      ],
    ],
  ],
];

Step 3: Access settings in React App

drupalSettings is a global variable so it can be used directly within the React app.

import React from 'react';
import ReactDOM from 'react-dom';

const root = ReactDOM.createRoot(document.getElementById('react-root'));
root.render(
  <>{drupalSettings.reactApp.setting1} {drupalSettings.reactApp.setting2}</>
);

Note: If any of the changes are not reflected on page refresh, try clearing browser or Drupal cache. You can also always call console.log (drupalSettings); in the browser console to debug.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *