Вопрос или проблема
У меня есть пользовательский блок списка постов, который я использую несколько раз на одной странице. На фронтенде я могу отслеживать ранее отрисованные посты и исключать их из последующих блоков. Но в редакторе это не так просто. Я попытался зарегистрировать хранилище, добавить отрисованные идентификаторы постов в состояние и отправить excludedPosts с fetch и исключить их в wp_query в ответе REST. Но это, похоже, не работает. Я не эксперт по react, поэтому не уверен, почему. Буду признателен за любые советы!
Вот моя текущая реализация:
import { __ } from '@wordpress/i18n';
import { createReduxStore, register, useDispatch, useSelect } from '@wordpress/data';
import apiFetch from '@wordpress/api-fetch';
import { useState, useEffect } from '@wordpress/element';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.css';
import PostListPost from './components/PostListPost';
const DEFAULT_STATE = {
excludedPosts: []
};
const actions = {
addExcludedPost(postId) {
return {
type: 'ADD_EXCLUDED_POST',
postId
}
},
removeExcludedPost(postId) {
return {
type: 'REMOVE_EXCLUDED_POST',
postId
}
}
};
const reducer = (state = DEFAULT_STATE, action) => {
switch (action.type) {
case 'ADD_EXCLUDED_POST':
return {
...state,
excludedPosts: [...state.excludedPosts, action.postId]
};
case 'REMOVE_EXCLUDED_POST':
return {
...state,
excludedPosts: state.excludedPosts.filter((postId) => postId !== action.postId)
};
default:
return state;
}
};
const selectors = {
getExcludedPosts(state) {
return state.excludedPosts;
}
};
const store = createReduxStore('my-post-list', {reducer, actions, selectors});
register(store);
export default function Edit({attributes, setAttributes}) {
const blockProps = useBlockProps();
const [posts, setPosts] = useState([]);
const {addExcludedPost} = useDispatch('my-post-list');
const excludedPosts = useSelect((select) => select('my-post-list').getExcludedPosts());
useEffect(() => {
apiFetch({
path: '/my-post-list/v1/posts',
method: 'POST',
data: {
...attributes,
excludedPosts: excludedPosts
}
}).then((response) => {
setPosts(response.posts);
response.posts.map(post => {
if (excludedPosts.indexOf(post.id) === -1) {
addExcludedPost(post.id);
}
});
});
}, [attributes]);
return (
<>
<div { ...blockProps }>
{posts.map((post) => {
return <PostListPost key={post.id} post={post} />
})}
</div>
</>
);
}
И функция ответа REST API:
function my_post_list_get_posts(WP_REST_Request $request) {
$params = $request->get_params();
$args = [
'post_type' => $params['postTypes'],
'post_status' => 'publish',
'posts_per_page' => $params['postsToShow'],
'post__not_in' => $params['excludedPosts'] ?? []
];
$query = new WP_Query($args);
$posts = [];
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$posts[] = [
'id' => get_the_ID(),
'title' => get_the_title(),
];
}
}
return [
'posts' => $posts,
];
}
add_action('rest_api_init', function () {
register_rest_route('my-post-list/v1', '/posts', [
'methods' => 'POST',
'callback' => 'my_post_list_get_posts',
'permission_callback' => '__return_true',
]);
});
Ответ или решение
Исключение ранее рендеренных постов в последующих блоках редактора: подробный разбор
Введение
Создание пользовательских компонентов в редакторе WordPress (Gutenberg) требует внимательного подхода, особенно когда речь идет о рендеринге постов. В данной статье мы рассмотрим проблему исключения ранее рендеренных постов в последующих блоках редактора, что важно для поддержания уникальности контента на странице.
Проблема
На текущий момент, ваша реализация пытается отслеживать уже отображенные посты и исключать их из выборки в новых блоках. Тем не менее, вы столкнулись с тем, что в редакторе не удается корректно исключить эти посты, несмотря на настройку Redux Store и изменения в wp_query
.
Решение
Чтобы эффективно решить проблему, давайте разберем шаги, которые можно предпринять для корректного функционирования вашего блока.
-
Проверка состояния Redux Store:
Убедитесь, что состояние вашего хранилища корректно обновляется. Проверьте, чтоexcludedPosts
правильно добавляет и удаляет идентификаторы постов. Для этого добавьте логирование в функции-редюсеры и действия, чтобы убедиться, что состояние корректно обновляется.case 'ADD_EXCLUDED_POST': console.log("Добавление исключенного поста:", action.postId); return { ...state, excludedPosts: [...state.excludedPosts, action.postId] };
Это поможет вам выявить возможные проблемы в том, как управляется состояние.
-
Проверка вызова API:
Ваша функцияmy_post_list_get_posts
обрабатывает входящие параметры. Убедитесь, чтоexcludedPosts
правильно передаются в запросе. Кроме того, используйтеconsole.log
в функции API, чтобы убедиться, что полученные параметры корректные:function my_post_list_get_posts(WP_REST_Request $request) { $params = $request->get_params(); error_log(print_r($params, true)); // Логирование параметров // ... }
-
Обновление состояний в компоненте:
Обратите внимание на порядок обновления состояний вuseEffect
. Вы должны обновить состояниеexcludedPosts
до выполнения запроса API для того, чтобы гарантировать, что в запрос отправляются актуальные данные.useEffect(() => { if (excludedPosts.length === 0) { return; // остановка эффекта, если нет исключенных постов } apiFetch({ path: '/my-post-list/v1/posts', method: 'POST', data: { ...attributes, excludedPosts: excludedPosts } }).then((response) => { setPosts(response.posts); response.posts.forEach(post => { if (!excludedPosts.includes(post.id)) { addExcludedPost(post.id); // добавление рендеренного поста } }); }); }, [attributes, excludedPosts]); // добавляем excludedPosts в зависимости
-
Оптимизация работы с данными:
Если ваши посты рендерятся на разных блоках, вы можете рассмотреть возможность хранения идентификаторов исключенных постов в атрибутах блока, чтобы предотвратить повторный вызов вызовов API и избежать дублирования. Например:setAttributes({ excludedPosts: [...excludedPosts, post.id] });
Это обеспечит более чистую и предсказуемую работу вашей реализации.
Заключение
Правильное исключение ранее рендеренных постов в редакторе Gutenberg потребует внимательного анализа работы вашего Redux Store, API запросов и управления состоянием компонентов. С помощью вышеописанных рекомендаций вы сможете оптимизировать свою реализацию, что позволит избежать дублирования контента в блоках на странице.
Советы по SEO
- Применение логов для отслеживания состояния и данных API обеспечивает лучшее понимание работы вашего кода, что помогает повысить его производительность.
- Убедитесь, что ваши компоненты непосредственно связаны с пользовательским опытом, предоставляя актуальные и уникальные данные, что приводит к повышению вовлеченности пользователей.
Следуя этим рекомендациям, вы сможете создать более эффективный и интуитивно понятный редактор постов в WordPress.