Drupal 8 e React.js

Neste tutorial, vou exemplificar a criação de um bloco no Drupal 8 que vai listar os comentários mais recentes do site em real time, utilizando o React.js.

O primeiro passo vai ser criar o módulo custom.

Para faciliar o desenvolvimento, vou utilizar o drupalconsole, tanto para gerar o módulo, quanto para criar o bloco via programação.

Gerando o módulo (drupal generate:module):

O segundo passo vai ser gerar o bloco que irá listar os comentários mais recentes (drupal generate:plugin:block).

O arquivo "/src/Plugin/Block/RecentComments.php" vai ficar da seguinte forma:

<?php

/**
 * @file
 * Contains \Drupal\reactjs_example\Plugin\Block\RecentComments.
 */

namespace Drupal\reactjs_example\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provides a 'RecentComments' block.
 *
 * @Block(
 *  id = "recent_comments",
 *  admin_label = @Translation("Recent comments"),
 * )
 */
class RecentComments extends BlockBase {


  /**
   * {@inheritdoc}
   */
  public function build() {
    $build = [];
    $build['recent_comments']['#markup'] = '<div id="recent-comments"></div>';
    $build['#attached']['library'][] = 'reactjs_example/recent.comments';

    return $build;
  }

}

Repare que dentro da função build, estou informando a library recent.comments. Vamos agora cria-la dentro da raiz do módulo.

Para saber mais sobre library e como adicionar JS no Drupal, veja aqui neste post.

Crie um arquivo com o nome "reactjs_example.libraries.yml". Nele, vamos informar o javascript responsável por recuperar os últimos comentários e também o React.js.

Conteúdo do arquivo "reactjs_example.libraries.yml":

recent.comments:
  version: VERSION
  js:
    js/recent-comments.js: {}
  dependencies:
    - reactjs_example/reactjs

reactjs:
  version: VERSION
  js:
    js/react.min.js: {}

Crie a pasta "js" na raiz do módulo e nela, coloque os arquivos react.min.js e o recent-comments.js.

Conteúdo do arquivo recent-comments.js:

/**
 * @file
 * Main JS file for react functionality.
 *
 */

(function ($) {

  Drupal.behaviors.react_blocks = {
    attach: function (context) {

      // A div with some text in it
      var CommentBox = React.createClass({displayName: 'CommentBox',

      loadCommentsFromServer: function() {
        $.ajax({
          url: this.props.url,
          dataType: 'json',
          success: function(data) {
            this.setState({data: data});
          }.bind(this),
          error: function(xhr, status, err) {
            console.error(this.props.url, status, err.toString());
          }.bind(this)
        });
      },

      getInitialState: function() {
        return {data: []};
      },

      componentDidMount: function() {
        this.loadCommentsFromServer();
        setInterval(this.loadCommentsFromServer, this.props.pollInterval);
      },

      render: function() {
          return (
            React.createElement("div", {className: "commentBox"}, 
              React.createElement("h3", null, React.createElement("b", null, "Check them out!")), 
              React.createElement(CommentList, {data: this.state.data})
            )
          );
        }
      });

      var CommentList = React.createClass({displayName: 'CommentList',
        render: function() {
          var commentNodes = this.props.data.map(function (comment) {
            return (
              React.createElement(Comment, {name: comment.name, subject: comment.subject}, 
                comment.subject
              )
            );
          });
          return (
            React.createElement("div", {className: "commentList"}, 
              commentNodes
            )
          );
        }
      });

      var Comment = React.createClass({displayName: 'Comment',
        render: function() {
          return (
            React.createElement("div", {className: "comment"}, 
              React.createElement("h2", {className: "commentAuthor"}, 
                this.props.name
              ), 
              this.props.subject
            )
          );
        }
      });

      // Render our reactComponent
      React.render(
        React.createElement(CommentBox, {url: "/api/v1/comments", pollInterval: 2000}),
        document.getElementById('recent-comments')
      );

    }
  }

})(jQuery);

Crédito do JS: Miles

O próximo passo é criar a View que irá servir os últimos comentários. Habilite o módulo "RESTful Web Services" e crie uma View do tipo REST.

A url dessa view será "api/v1/comments" e conterá os campos "Title" e "Author". Exemplo:

 Por úlitmo, habilite o módulo reactjs_example. Adicione o bloco em alguma região do site e veja seu resultado final.

 

Crédito da Imagem: Miles

Faça o download do módulo completo aqui. Você também pode importar a View utilizada neste tutorial, utilizando o arquivo "import_views.txt".

Este módulo foi uma adaptação de drupal-react_blocks (Drupal 7) escrito por Miles.

 

Até o próximo Post!

Login do usuário