diff --git a/core-blocks/latest-posts/edit.js b/core-blocks/latest-posts/edit.js index f269ce2014c1d..735f983d29dcf 100644 --- a/core-blocks/latest-posts/edit.js +++ b/core-blocks/latest-posts/edit.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { get, isUndefined, pickBy } from 'lodash'; +import { isUndefined, pickBy } from 'lodash'; import moment from 'moment'; import classnames from 'classnames'; @@ -17,7 +17,6 @@ import { Spinner, ToggleControl, Toolbar, - withAPIData, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; @@ -26,7 +25,7 @@ import { BlockAlignmentToolbar, BlockControls, } from '@wordpress/editor'; -import { addQueryArgs } from '@wordpress/url'; +import { withSelect } from '@wordpress/data'; /** * Internal dependencies @@ -50,8 +49,7 @@ class LatestPostsEdit extends Component { } render() { - const latestPosts = this.props.latestPosts.data; - const { attributes, categoriesList, setAttributes } = this.props; + const { attributes, categoriesList, setAttributes, latestPosts } = this.props; const { displayPostDate, align, postLayout, columns, order, orderBy, categories, postsToShow } = attributes; const inspectorControls = ( @@ -60,7 +58,7 @@ class LatestPostsEdit extends Component { setAttributes( { order: value } ) } onOrderByChange={ ( value ) => setAttributes( { orderBy: value } ) } @@ -158,21 +156,20 @@ class LatestPostsEdit extends Component { } } -export default withAPIData( ( props ) => { +export default withSelect( ( select, props ) => { const { postsToShow, order, orderBy, categories } = props.attributes; + const { getEntityRecords } = select( 'core' ); const latestPostsQuery = pickBy( { categories, order, orderby: orderBy, per_page: postsToShow, - _fields: [ 'date_gmt', 'link', 'title' ], }, ( value ) => ! isUndefined( value ) ); const categoriesListQuery = { per_page: 100, - _fields: [ 'id', 'name', 'parent' ], }; return { - latestPosts: addQueryArgs( '/wp/v2/posts', latestPostsQuery ), - categoriesList: addQueryArgs( '/wp/v2/categories', categoriesListQuery ), + latestPosts: getEntityRecords( 'postType', 'post', latestPostsQuery ), + categoriesList: getEntityRecords( 'taxonomy', 'category', categoriesListQuery ), }; } )( LatestPostsEdit ); diff --git a/docs/blocks/creating-dynamic-blocks.md b/docs/blocks/creating-dynamic-blocks.md index 1149766eb9c86..cb1a34bfc7b28 100644 --- a/docs/blocks/creating-dynamic-blocks.md +++ b/docs/blocks/creating-dynamic-blocks.md @@ -11,29 +11,26 @@ The following code example shows how to create the latest post block dynamic blo var el = wp.element.createElement, registerBlockType = wp.blocks.registerBlockType, - withAPIData = wp.components.withAPIData; + withSelect = wp.data.withSelect; registerBlockType( 'my-plugin/latest-post', { title: 'Latest Post', icon: 'megaphone', category: 'widgets', - edit: withAPIData( function() { + edit: withSelect( function( select ) { return { - posts: '/wp/v2/posts?per_page=1' + posts: select( 'core' ).getEntityRecords( 'postType', 'post' ) }; } )( function( props ) { - if ( ! props.posts.data ) { - return "loading !"; - } - if ( props.posts.data.length === 0 ) { + if ( props.posts && props.posts.length === 0 ) { return "No posts"; } var className = props.className; - var post = props.posts.data[ 0 ]; - + var post = props.posts[ 0 ]; + return el( - 'a', + 'a', { className: className, href: post.link }, post.title.rendered ); @@ -50,26 +47,23 @@ registerBlockType( 'my-plugin/latest-post', { // myblock.js const { registerBlockType } = wp.blocks; -const { withAPIData } = wp.components; +const { withSelect } = wp.data; registerBlockType( 'my-plugin/latest-post', { title: 'Latest Post', icon: 'megaphone', category: 'widgets', - edit: withAPIData( () => { + edit: withSelect( ( select ) => { return { - posts: '/wp/v2/posts?per_page=1' + posts: select( 'core' ).getEntityRecords( 'postType', 'post' ) }; } )( ( { posts, className } ) => { - if ( ! posts.data ) { - return "loading !"; - } - if ( posts.data.length === 0 ) { + if ( posts && posts.length === 0 ) { return "No posts"; } - var post = posts.data[ 0 ]; - + var post = posts[ 0 ]; + return { post.title.rendered } ; @@ -119,7 +113,7 @@ There are a few things to notice: ## Live rendering in Gutenberg editor -Gutenberg 2.8 added the [``](https://github.com/WordPress/gutenberg/tree/master/packages/components/src/server-side-render) block which enables all the rendering to take place on the server using PHP rather than in JavaScript. Server-side render is meant as a fallback; client-side rendering in JavaScript is the preferred implementation. +Gutenberg 2.8 added the [``](https://github.com/WordPress/gutenberg/tree/master/packages/components/src/server-side-render) block which enables all the rendering to take place on the server using PHP rather than in JavaScript. Server-side render is meant as a fallback; client-side rendering in JavaScript is the preferred implementation. {% codetabs %} {% ES5 %} diff --git a/docs/reference/deprecated.md b/docs/reference/deprecated.md index f5d7b0497089b..49c8775c12de4 100644 --- a/docs/reference/deprecated.md +++ b/docs/reference/deprecated.md @@ -1,5 +1,9 @@ Gutenberg's deprecation policy is intended to support backwards-compatibility for two minor releases, when possible. The current deprecations are listed below and are grouped by _the version at which they will be removed completely_. If your plugin depends on these behaviors, you must update to the recommended alternative before the noted version. +## 3.7.0 + + - `wp.components.withAPIData` has been removed. Please use the Core Data module or `wp.apiFetch` directly instead. + ## 3.6.0 - `wp.editor.editorMediaUpload` has been removed. Please use `wp.editor.mediaUpload` instead. diff --git a/packages/components/src/higher-order/with-api-data/index.js b/packages/components/src/higher-order/with-api-data/index.js index a3c2c4af0935b..c57ffc6786417 100644 --- a/packages/components/src/higher-order/with-api-data/index.js +++ b/packages/components/src/higher-order/with-api-data/index.js @@ -9,6 +9,7 @@ import { mapValues, reduce, forEach, noop } from 'lodash'; import { Component } from '@wordpress/element'; import { createHigherOrderComponent } from '@wordpress/compose'; import isShallowEqual from '@wordpress/is-shallow-equal'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -17,6 +18,12 @@ import request, { getCachedResponse } from './request'; import { getRoute } from './routes'; export default ( mapPropsToData ) => createHigherOrderComponent( ( WrappedComponent ) => { + deprecated( 'wp.components.withAPIData', { + version: 3.7, + plugin: 'Gutenberg', + alternative: 'the Core Data Module or wp.apiFetch directly', + } ); + class APIDataComponent extends Component { constructor( props, context ) { super( ...arguments ); diff --git a/packages/components/src/higher-order/with-api-data/test/index.js b/packages/components/src/higher-order/with-api-data/test/index.js index 504b52dbc295e..fdfbb85f7da33 100644 --- a/packages/components/src/higher-order/with-api-data/test/index.js +++ b/packages/components/src/higher-order/with-api-data/test/index.js @@ -114,6 +114,7 @@ describe( 'withAPIData()', () => { 'path', ] ); expect( getDataProps( wrapper ).revisions.isLoading ).toBe( true ); + expect( console ).toHaveWarned(); process.nextTick( () => { expect( getDataProps( wrapper ).revisions.isLoading ).toBe( false ); diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 7cde3e09032d0..ffcd414ea61f7 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -22,6 +22,7 @@ export const defaultEntities = [ export const kinds = [ { name: 'postType', loadEntities: loadPostTypeEntities }, + { name: 'taxonomy', loadEntities: loadTaxonomyEntities }, ]; /** @@ -40,6 +41,22 @@ async function loadPostTypeEntities() { } ); } +/** + * Returns the list of the taxonomies entities. + * + * @return {Promise} Entities promise + */ +async function loadTaxonomyEntities() { + const taxonomies = await apiFetch( { path: '/wp/v2/taxonomies?context=edit' } ); + return map( taxonomies, ( taxonomy, name ) => { + return { + kind: 'taxonomy', + baseURL: '/wp/v2/' + taxonomy.rest_base, + name, + }; + } ); +} + /** * Returns the entity's getter method name given its kind and name. * diff --git a/packages/editor/src/components/page-attributes/parent.js b/packages/editor/src/components/page-attributes/parent.js index ed9ab45218089..ca0a4acaf4246 100644 --- a/packages/editor/src/components/page-attributes/parent.js +++ b/packages/editor/src/components/page-attributes/parent.js @@ -7,10 +7,9 @@ import { get } from 'lodash'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { TreeSelect, withAPIData } from '@wordpress/components'; +import { TreeSelect } from '@wordpress/components'; import { compose } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; -import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -20,7 +19,7 @@ import { buildTermsTree } from '../../utils/terms'; export function PageAttributesParent( { parent, postType, items, onUpdateParent } ) { const isHierarchical = get( postType, [ 'hierarchical' ], false ); const parentPageLabel = get( postType, [ 'labels', 'parent_item_colon' ] ); - const pageItems = get( items, [ 'data' ], [] ); + const pageItems = items || []; if ( ! isHierarchical || ! parentPageLabel || ! pageItems.length ) { return null; } @@ -42,14 +41,24 @@ export function PageAttributesParent( { parent, postType, items, onUpdateParent } const applyWithSelect = withSelect( ( select ) => { - const { getPostType } = select( 'core' ); + const { getPostType, getEntityRecords } = select( 'core' ); const { getCurrentPostId, getEditedPostAttribute } = select( 'core/editor' ); const postTypeSlug = getEditedPostAttribute( 'type' ); + const postType = getPostType( postTypeSlug ); + const postId = getCurrentPostId(); + const isHierarchical = get( postType, [ 'hierarchical' ], false ); + const query = { + per_page: -1, + exclude: postId, + parent_exclude: postId, + orderby: 'menu_order', + order: 'asc', + }; + return { - postId: getCurrentPostId(), parent: getEditedPostAttribute( 'parent' ), - postType: getPostType( postTypeSlug ), - postTypeSlug, + items: isHierarchical ? getEntityRecords( 'postType', postTypeSlug, query ) : [], + postType, }; } ); @@ -62,25 +71,7 @@ const applyWithDispatch = withDispatch( ( dispatch ) => { }; } ); -const applyWithAPIDataItems = withAPIData( ( { postType, postId } ) => { - const isHierarchical = get( postType, [ 'hierarchical' ], false ); - const restBase = get( postType, [ 'rest_base' ], false ); - const query = { - context: 'edit', - per_page: -1, - exclude: postId, - parent_exclude: postId, - _fields: [ 'id', 'parent', 'title' ], - orderby: 'menu_order', - order: 'asc', - }; - return isHierarchical && restBase ? - { items: addQueryArgs( `/wp/v2/${ restBase }`, query ) } : - {}; -} ); - export default compose( [ applyWithSelect, applyWithDispatch, - applyWithAPIDataItems, ] )( PageAttributesParent );