{"id":228855,"date":"2022-10-18T11:09:00","date_gmt":"2022-10-18T08:09:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=228855"},"modified":"2022-11-09T04:32:53","modified_gmt":"2022-11-09T01:32:53","slug":"usando-o-wordpress-block-editor-gutenberg-com-a-api-rest","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/usando-o-wordpress-block-editor-gutenberg-com-a-api-rest\/","title":{"rendered":"Usando o WordPress Block Editor (Gutenberg) com a API REST"},"content":{"rendered":"\n<p>No meu artigo anterior, falei sobre <a href=\"https:\/\/wholesomecode.ltd\/articles\/wp_query-and-the-wordpress-block-editor-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">como percorrer as postagens e os tipos de postagem personalizados no Gutenberg<\/a>. Neste post eu falo sobre como receber e usar dados personalizados dentro do Gutenberg dos endpoints da API REST do WordPress.<\/p>\n<p>Neste exemplo vamos:<\/p>\n<p><strong>A API REST nem sempre \u00e9 o caminho certo.<\/strong><\/p>\n<p>*Usamos <code>get_option<\/code>na API REST apenas como exemplo. Se voc\u00ea s\u00f3 precisa de acesso a uma op\u00e7\u00e3o e n\u00e3o pretende alterar seu estado, pode usar <code>wp_localize_script<\/code>para passar as op\u00e7\u00f5es para JavaScript.<\/p>\n<p>Se voc\u00ea quiser acessar uma op\u00e7\u00e3o E alterar seu estado, recomendo ler meu <a href=\"https:\/\/wholesomecode.ltd\/guides\/options-settings-data-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">guia sobre como armazenar configura\u00e7\u00f5es e dados na tabela de op\u00e7\u00f5es com o Gutenberg usando a API de configura\u00e7\u00f5es<\/a> .*<\/p>\n<h2>Criando um endpoint da API REST<\/h2>\n<p>Vamos criar um endpoint de API REST simples que retorna o valor de uma op\u00e7\u00e3o do WordPress (usando <code>get_option<\/code>).<\/p>\n<pre><code>function wcltd_get_option() {\n    register_rest_route(\n        'wcltd\/wholesome-plugin\/v1',\n        '\/get\/option\/(?P&lt;option&gt;([A-Za-z0-9_])+)\/',\n        array(\n            'callback'            =&gt; function ($request) {\n                $option = isset( $request['option'] )? esc_attr( $request['option'] ): null;\n                $value  = get_option( $option, '' );\n                return $value;\n            },\n            'methods'             =&gt; 'GET',) );\n}\nadd_action( 'rest_api_init', 'wcltd_get_option' );\n<\/code><\/pre>\n<p>Depois de criar este ponto de extremidade, certifique-se de <strong>salvar novamente seus permalinks<\/strong> para que ele seja ativado. Observe que existem maneiras melhores de fazer isso (como usar <code>flush_rewrite_rules()<\/code>no <code>register_activation_hook<\/code>), mas para este exemplo, um novo salvamento r\u00e1pido ser\u00e1 suficiente.<\/p>\n<p>Agora, quando passarmos a URL <code>\/wp-json\/wcltd\/wholesome-plugin\/v1\/get\/option\/test\/<\/code>(depois do seu pr\u00f3prio dom\u00ednio, obviamente) para o nosso navegador, ela retornar\u00e1 um valor, que pode ser uma string vazia <code>''<\/code>ou o valor da op\u00e7\u00e3o, se definida.<\/p>\n<p><a href=\"https:\/\/cdn.hashnode.com\/res\/hashnode\/image\/upload\/v1639990082853\/S6umfXuzNF.png\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Nosso endpoint, retornando uma string vazia<\/a> Nosso endpoint, retornando uma string vazia<\/p>\n<p>Observe que eu comentei propositadamente as linhas 12-14, o que garantiria que apenas algu\u00e9m que tenha <code>edit_post<\/code>direitos possa executar o c\u00f3digo se for deixado. No entanto, com isso comentado, n\u00e3o podemos testar o c\u00f3digo em nosso navegador.<\/p>\n<p>Tente adicionar algum c\u00f3digo para dar um valor \u00e0 sua op\u00e7\u00e3o e veja o que ela retorna. Por exemplo, se eu fosse executar o seguinte c\u00f3digo antes da minha fun\u00e7\u00e3o:<\/p>\n<pre><code>update_option( 'wcltd_example_option', 'Hello World' );\n<\/code><\/pre>\n<p>Agora, se eu atingir o endpoint <code>\/wp-json\/wcltd\/wholesome-plugin\/v1\/get\/option\/wcltd_example_option\/<\/code>, obterei a seguinte sa\u00edda:<\/p>\n<p>Nosso endpoint, retornando alguns dados.<\/p>\n<h2>Registrando um reposit\u00f3rio de dados<\/h2>\n<p>Agora que temos um endpoint da API REST, podemos criar um armazenamento de dados com <code>registerStore<\/code>.<\/p>\n<p><code>registerStore<\/code>fornece um armazenamento de dados semelhante ao Redux, que nos permite gerenciar o estado em nosso aplicativo. Ele tamb\u00e9m suporta resolvedores, que nos permitem preencher o estado de uma fonte externa (como nossa API REST).<\/p>\n<p>Voc\u00ea pode <a href=\"https:\/\/reactjs.org\/docs\/state-and-lifecycle.html\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ler mais sobre o estado REACT na documenta\u00e7\u00e3o oficial<\/a>.<\/p>\n<p>Aqui est\u00e1 como podemos criar uma loja (como <code>store.js<\/code>em nosso projeto que nos permitir\u00e1 extrair dados do nosso endpoint da API REST.<\/p>\n<h3>Depend\u00eancias<\/h3>\n<p>Precisaremos extrair <code>apiFetch<\/code>e <code>registerStore<\/code>de nossas depend\u00eancias do WordPress.<\/p>\n<pre><code>import apiFetch from '@wordpress\/api-fetch';\nimport { registerStore } from '@wordpress\/data';\n<\/code><\/pre>\n<h3>Seletores<\/h3>\n<p>A primeira coisa que queremos fazer \u00e9 criar uma fun\u00e7\u00e3o seletora, em um objeto chamado &#8216;seletores&#8217;.<\/p>\n<p>Tudo o que isso faz \u00e9 extrair a &#8216;op\u00e7\u00e3o&#8217; do estado e devolv\u00ea-la.<\/p>\n<pre><code>const selectors = {\n    getOption( state, optionKey) {\n        const { option } = state;\n        return option;\n    },\n};\n<\/code><\/pre>\n<h3>Resolvedores<\/h3>\n<p>O resolvedor \u00e9 um efeito colateral do seletor e faz um pouco mais.<\/p>\n<p>Aqui criamos nossa fun\u00e7\u00e3o que pega nossa optionKey e passa um endpoint da API REST para nossas a\u00e7\u00f5es (que definiremos a seguir).<\/p>\n<p>Isso define a op\u00e7\u00e3o, com outra chamada para nossas a\u00e7\u00f5es.<\/p>\n<pre><code>const resolvers = {\n    *getOption( optionKey) {\n        const option = yield actions.getOption(\n            '\/wcltd\/wholesome-plugin\/v1\/get\/option\/' + optionKey + '\/',\n        );\n        return actions.setOption( option );\n    },\n};\n<\/code><\/pre>\n<h3>A\u00e7\u00f5es<\/h3>\n<p>As duas fun\u00e7\u00f5es em um objeto chamado <code>actions<\/code>que chamamos anteriormente s\u00e3o definidas aqui.<\/p>\n<p>Eles indicam qual controle ou redutor vamos usar para definir ou obter o valor.<\/p>\n<pre><code>const actions = {\n    setOption( option) {\n        return {\n            type: 'SET_OPTION',\n            option,\n        };\n    },\n    getOption( path) {\n        return {\n            type: 'GET_OPTION',\n            path,\n        };\n    },\n};\n<\/code><\/pre>\n<h3>Controles<\/h3>\n<p>Em nossos controles temos o <code>GET_OPTION<\/code>que faz a API chamar usando <code>apiFetch<\/code>e o caminho que definimos anteriormente.<\/p>\n<pre><code>const controls = {\n    GET_OPTION( action) {\n        return apiFetch( { path: action.path } );\n    },\n};\n<\/code><\/pre>\n<h3>Redutor<\/h3>\n<p>Em nossa fun\u00e7\u00e3o redutor temos <code>SET_OPTION<\/code>que pega nosso valor (neste caso <code>option<\/code>, e define seu estado.<\/p>\n<pre><code>function reducer( state = { option: '' }, action) {\n    switch (action.type) {\n        case 'SET_OPTION':\n            return {\n                ...state,\n                option: action.option,\n            };\n    }\n    return state;\n};\n<\/code><\/pre>\n<h3>Cadastrando a loja<\/h3>\n<p>Finalmente, registramos uma loja, damos a ela um namespace para que possamos acess\u00e1-la e passamos um objeto de todos os objetos e fun\u00e7\u00f5es acima.<\/p>\n<pre><code>const store = registerStore(\n    'wcltd\/wholesome-plugin\/data',\n    {\n        actions,\n        controls,\n        reducer,\n        resolvers,\n        selectors,\n    }\n);\n\nexport default store;\n<\/code><\/pre>\n<p>exportar armazenamento padr\u00e3o;<\/p>\n<h2>Usando os dados com um bloco<\/h2>\n<p>Vamos expandir o <a href=\"https:\/\/wholesomecode.ltd\/articles\/an-overview-of-the-wordpress-create-block-script\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">bloco criado pelo <code>@wordpress\/create-block<\/code>script, sobre o qual escrevi anteriormente<\/a> para nos conectar a um endpoint da API REST.<\/p>\n<p>Crie um arquivo na <code>\/src<\/code>pasta chamada <code>store.js<\/code>e copie todo o c\u00f3digo acima para ele:<\/p>\n<pre><code>import apiFetch from '@wordpress\/api-fetch';\nimport { registerStore } from '@wordpress\/data';\n\nconst selectors = {\n    getOption( state, optionKey) {\n        const { option } = state;\n        return option;\n    },\n};\n\nconst resolvers = {\n    *getOption( optionKey) {\n        const option = yield actions.getOption(\n            '\/wcltd\/wholesome-plugin\/v1\/get\/option\/' + optionKey + '\/',\n        );\n        return actions.setOption( option );\n    },\n};\n\nconst actions = {\n    setOption( option) {\n        return {\n            type: 'SET_OPTION',\n            option,\n        };\n    },\n    getOption( path) {\n        return {\n            type: 'GET_OPTION',\n            path,\n        };\n    },\n};\n\nconst controls = {\n    GET_OPTION( action) {\n        return apiFetch( { path: action.path } );\n    },\n};\n\nfunction reducer( state = { option: '' }, action) {\n    switch (action.type) {\n        case 'SET_OPTION':\n            return {\n                ...state,\n                option: action.option,\n            };\n    }\n    return state;\n};\n\nconst store = registerStore(\n    'wcltd\/wholesome-plugin\/data',\n    {\n        actions,\n        controls,\n        reducer,\n        resolvers,\n        selectors,\n    }\n);\n\nexport default store;\n<\/code><\/pre>\n<p>Agora edite nosso <code>\/src\/index.js<\/code>arquivo para incluir o <code>store.js<\/code>arquivo:<\/p>\n<pre><code>\nimport store from '.\/store';\nimport Edit from '.\/edit';\nimport save from '.\/save';\n<\/code><\/pre>\n<p>Tamb\u00e9m precisamos garantir que inclu\u00edmos <code>withSelect<\/code>no topo do nosso arquivo:<\/p>\n<pre><code>import { withSelect } from '@wordpress\/data';\n<\/code><\/pre>\n<p>Em seguida, vamos envolver nosso m\u00f3dulo Edit <code>withSelect<\/code>para fazer a chamada da API REST para nossa op\u00e7\u00e3o, assim:<\/p>\n<pre><code>\nedit: withSelect( (select) =&gt; {\n    const option = select( 'wcltd\/wholesome-plugin\/data' ).getOption( 'wcltd_example_option' );\n    return {\n        option,\n    };\n} )( Edit ),\n<\/code><\/pre>\n<p>Agora podemos acessar <code>option<\/code>em nossas props dentro de <code>edit.js<\/code>, assim:<\/p>\n<pre><code>export default function Edit( { className, option }) {\n    return (&lt;p className={ className }&gt;\n            { option }\n        &lt;\/p&gt;\n    );\n}\n<\/code><\/pre>\n<p>Por fim, vamos visualizar nosso bloco no editor e ver o que obtemos:<\/p>\n<p><a href=\"https:\/\/cdn.hashnode.com\/res\/hashnode\/image\/upload\/v1639990090843\/2uT6sdoTo.png\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">A sa\u00edda no editor de blocos.<\/a> A sa\u00edda no editor de blocos.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/wholesomecode.ltd\" class=\"external external_icon\">wholesomecode.ltd<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>No meu artigo anterior, falei sobre como percorrer as postagens e os tipos de postagem personalizados no Gutenberg. Neste post eu falo sobre como receber e usar dados customizados dentro do Gutenberg f&#8230;<\/p>\n","protected":false},"author":1,"featured_media":220671,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,722,920,867],"tags":[1170],"class_list":["post-228855","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-outro","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/228855","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=228855"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/228855\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/220671"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=228855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=228855"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=228855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}