What is the difference between select(‘core’) vs apiFetch, and when to use which?

This is a very important architectural decision in Gutenberg β€” and honestly, many developers misuse both.

Let’s break it down in a practical, real-world way so you can decide like a tech lead πŸ‘‡


🧠 select('core') vs apiFetch β€” What’s the Difference?

Featureselect('core')apiFetch
Data SourceWP Data Store (core-data)Direct REST API
Reactivityβœ… Reactive (auto re-render)❌ Not reactive
Cachingβœ… Built-in caching❌ No caching
Performanceβœ… Optimized⚠️ Depends on usage
Ease of Useβœ… Cleaner in blocks⚠️ More manual
Control⚠️ Limitedβœ… Full control

βœ… When You Should Use select('core') (Recommended Most of the Time)

πŸ‘‰ Use this inside Gutenberg blocks/UI

βœ” Best for:

  • Fetching posts, pages, users
  • Displaying dynamic data in UI
  • When you want automatic updates
  • When performance matters

Example

const posts = useSelect((select) => {
return select('core').getEntityRecords('postType', 'post');
}, []);

πŸ’‘ Why it’s better

  • Uses centralized state (Redux-like store)
  • Avoids duplicate API calls
  • Auto re-renders UI when data changes
  • Works seamlessly with Gutenberg

⚠️ When apiFetch is Better

πŸ‘‰ Use this when you need full control or custom behavior

βœ” Best for:

  • Custom REST API endpoints
  • POST / PUT / DELETE requests
  • Non-Gutenberg environments
  • One-time operations (form submit, migration scripts, etc.)

Example

import apiFetch from '@wordpress/api-fetch';const fetchData = async () => {
const posts = await apiFetch({
path: '/wp/v2/posts?per_page=5',
}); console.log(posts);
};

🚨 Common Mistake (Very Important)

❌ Using apiFetch inside React render logic:

// ❌ BAD PRACTICE
const posts = await apiFetch({ path: '/wp/v2/posts' });

πŸ‘‰ This causes:

  • Multiple API calls
  • No caching
  • Performance issues

⚑ Real-World Decision Rule (Use This)

πŸ‘‰ Ask yourself:

1. Is this UI data inside Gutenberg?

πŸ‘‰ βœ… Use select('core')


2. Is this a custom API or action (POST/UPDATE)?

πŸ‘‰ βœ… Use apiFetch


3. Do I need caching + reactivity?

πŸ‘‰ βœ… Use select('core')


4. Do I need full control over request?

πŸ‘‰ βœ… Use apiFetch


πŸ† Best Practice (Senior-Level Pattern)

πŸ‘‰ Combine both when needed:

  • Use select('core') β†’ for reading data
  • Use apiFetch β†’ for writing/updating data

Example Pattern

// Read (cached + reactive)
const posts = useSelect((select) =>
select('core').getEntityRecords('postType', 'post')
);// Write (manual control)
const createPost = async () => {
await apiFetch({
path: '/wp/v2/posts',
method: 'POST',
data: { title: 'New Post' },
});
};

🧩 Bonus Insight (Interview-Level)

πŸ‘‰ select('core') internally:

  • Uses @wordpress/core-data
  • Wraps REST API calls
  • Adds caching + resolution tracking
  • Prevents duplicate requests

🏁 Final Verdict

πŸ‘‰ If you’re building Gutenberg blocks:

Use select('core') 80–90% of the time

πŸ‘‰ Use apiFetch only when:

  • You need custom logic
  • Or you’re mutating data

Leave a Reply

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