Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is withAPIData being deprecated? #7390

Closed
mrleemon opened this issue Jun 20, 2018 · 11 comments
Closed

Is withAPIData being deprecated? #7390

mrleemon opened this issue Jun 20, 2018 · 11 comments

Comments

@mrleemon
Copy link
Contributor

@mrleemon mrleemon commented Jun 20, 2018

I've seen some mentions here about withAPIData being deprecated in the near future. I'm using this component in a couple of blocks I'm developing and I don't know which is the alternative method to get dynamic data. I see that the Latest Posts block is still using it, so I don't know how to proceed.

Would someone point me to the right direction, please?

Thanks

@gziolo
Copy link
Member

@gziolo gziolo commented Jun 20, 2018

Yes, correct. We are planning to deprecate it soon.

It's not marked as deprecated yet, because we still use it in a few places, but it's something we want to replace with data module. An alternative approach would be to use withSelect to fetch data like in the Categories block:

export default withSelect( ( select ) => {
const { getCategories, isRequestingCategories } = select( 'core' );
return {
categories: getCategories(),
isRequesting: isRequestingCategories(),
};
} )( CategoriesEdit );

getCategories has also a corresponding resolver which triggers network requests and ensures that the data store is updated with the response data which comes from the server:

export async function* getCategories() {
const categories = await apiRequest( { path: '/wp/v2/categories?per_page=-1' } );
yield receiveTerms( 'categories', categories );
}

In addition, we offer a selector which verifies if the request is in progress:

export function isRequestingCategories() {
return isResolving( 'getCategories' );
}

Related docs:

@mrleemon
Copy link
Contributor Author

@mrleemon mrleemon commented Jun 20, 2018

It might be a good idea to update the handbook section dedicated to building dynamic blocks cause it still makes reference to withAPIData:

https://wordpress.org/gutenberg/handbook/blocks/creating-dynamic-blocks/

@gziolo
Copy link
Member

@gziolo gziolo commented Jun 20, 2018

Good catch, I opened #7397. Thanks!

@IacopoC
Copy link

@IacopoC IacopoC commented Aug 14, 2018

I don't know if this is the right place to comment but I'm experiencing a malfunction of the code with withSelect that is now proposed in the documentation here
. An older version with withAPIData works without errors, I don't know exactly why.

@mattwatsoncodes
Copy link

@mattwatsoncodes mattwatsoncodes commented Aug 14, 2018

Hi there, I also don't know if this is the correct place to comment, but following the new guidance I cannot get withSelect to work where I previously used withAPIData. I am trying to setup a custom API endpoint for the call.

My issue is that the 'controls' section of the recomended registerStore never fires. In the documentation it says that this is an opt-in component, and I need to enable it via the use command, however this is undefined by default in v3.5.0 so I have to import it via @wordpress/data, this however then gives me lodash conflicts.

Even after all that, I'm not sure if I am going down the right path. withAPIData was pretty simple for me to understand, but I must admit I'm a little lost now.

For some more examples of my specific issue, I've wrote about my problem on stackexchange here: https://wordpress.stackexchange.com/questions/311431/in-gutenberg-now-that-withapidata-is-being-deprecated-how-can-i-do-an-async-ca if its of any help.

@mattwatsoncodes
Copy link

@mattwatsoncodes mattwatsoncodes commented Aug 15, 2018

@IacopoC I've now answered my own question, it may help you too: https://wordpress.stackexchange.com/a/311551/148566

Here is my solution:

const { apiFetch }          = wp;
const {
	registerStore,
	withSelect,
} = wp.data;

const actions = {
	setUserRoles( userRoles ) {
		return {
			type: 'SET_USER_ROLES',
			userRoles,
		};
	},

	receiveUserRoles( path ) {
		return {
			type: 'RECEIVE_USER_ROLES',
			path,
		};
	},
};

const store = registerStore( 'matt-watson/secure-block', {
	reducer( state = { userRoles: {} }, action ) {

		switch ( action.type ) {
			case 'SET_USER_ROLES':
				return {
					...state,
					userRoles: action.userRoles,
				};
			case 'RECEIVE_USER_ROLES':
				return action.userRoles;
		}

		return state;
	},

	actions,

	selectors: {
		receiveUserRoles( state ) {
			const { userRoles } = state;
			return userRoles;
		},
	},

	resolvers: {
		* receiveUserRoles( state ) {
			const userRoles = apiFetch( { path: '/matt-watson/secure-blocks/v1/user-roles/' } )
				.then( userRoles => {
					return actions.setUserRoles( userRoles );
				} )
			yield userRoles;
		},
	},

} );

By doing this you can access this via withSelect like so:

edit: withSelect( ( select ) => {
				return {
					roles: select('matt-watson/secure-block').receiveUserRoles(),
				};
			} )( props => {

@IacopoC
Copy link

@IacopoC IacopoC commented Aug 16, 2018

@mwtsn Thank you

@phpbits
Copy link
Contributor

@phpbits phpbits commented Nov 3, 2018

@mattwatsoncodes @gziolo The latest dev version is returning the error below :

Uncaught (in promise) Error: Actions must be plain objects. Use custom middleware for async actions.

Hoping you can point me out on the best solution. Thanks!

@nerrad
Copy link
Contributor

@nerrad nerrad commented Nov 5, 2018

For those stumbling on this in search be aware that this pull has examples that will no longer work because of api changes in the wp.data package. More up-to-date examples and current documentation can be found here: https://github.com/WordPress/gutenberg/tree/master/packages/data

@code-flow
Copy link
Contributor

@code-flow code-flow commented Nov 22, 2018

@phpbits I had the problem with the "Uncaught (in promise) Error: Actions must be plain objects." warning and found a solution to that. It seems that the resolver methods no longer retrieve the state.

So in the example on this page, this code

resolvers: {
* getPrice( state, item ) {
    const path = '/wp/v2/prices/' + item;
    const price = yield actions.fetchFromAPI( path );
    return actions.setPrice( item, price );
  },
}

need to be changed to this:

resolvers: {
* getPrice( item ) {
    const path = '/wp/v2/prices/' + item;
    const price = yield actions.fetchFromAPI( path );
    return actions.setPrice( item, price );
  },
}

Plus: If you're using an old example, please note that you no need a control method in your store. The page that I've linked says that "This can be particularly useful in implementing asynchronous data flows"

Hope this helps you as well.

@mattwatsoncodes
Copy link

@mattwatsoncodes mattwatsoncodes commented Dec 10, 2018

Thanks @phpbits @nerrad @code-flow the updated code for my solution is as follows:

const actions = {
	setUserRoles( userRoles ) {
		return {
			type: 'SET_USER_ROLES',
			userRoles,
		};
	},
	receiveUserRoles( path ) {
		return {
			type: 'RECEIVE_USER_ROLES',
			path,
		};
	},
};

const store = registerStore( 'matt-watson/secure-block', {
	reducer( state = { userRoles: {} }, action ) {

		switch ( action.type ) {
			case 'SET_USER_ROLES':
				return {
					...state,
					userRoles: action.userRoles,
				};
		}

		return state;
	},

	actions,

	selectors: {
		receiveUserRoles( state ) {
			const { userRoles } = state;
			return userRoles;
		},
	},

	controls: {
		RECEIVE_USER_ROLES( action ) {
			return apiFetch( { path: action.path } );
		},
	},

	resolvers: {
		* receiveUserRoles( state ) {
			const userRoles = yield actions.receiveUserRoles( '/matt-watson/secure-blocks/v1/user-roles/' );
			return actions.setUserRoles( userRoles );
		},
	},
} );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants