Вопрос или проблема
Я работаю над проектом с использованием Gatsby и Drupal CMS и в настоящее время сталкиваюсь с проблемой, связанной с gatsby-plugin-image и изображениями, приходящими из CMS.
Я пытаюсь заменить все свои теги <img>
на компоненты, но, похоже, я пропускаю что-то в определении типа или запросе GraphQL, так как получаю это предупреждение во время процесса сборки:
warn Вы не можете использовать childImageSharp вместе с undefined.undefined — используйте вместо этого publicURL. Часть запроса childImageSharp в этом файле вернет null:undefined
Вот мое определение типа для соответствующего параграфа Drupal:
module.exports = schema => [
schema.buildObjectType({
name: 'paragraph__image',
fields: {
id: 'ID!',
drupal_id: 'String',
drupal_internal__id: 'Int',
drupal_internal__revision_id: 'Int',
status: 'Boolean',
internal: 'Internal!',
type: {
type: 'String',
resolve: source => source.internal.type || '',
},
legend: {
type: 'String',
resolve: source =>
source.field_paragraph_image_legend
? source.field_paragraph_image_legend || ''
: '',
},
image: {
type: 'Image',
resolve: (source, args, context) => {
const imageFile = context.nodeModel.getNodeById({
type: 'file__image',
id: source.relationships.field_paragraph_image_image___NODE,
});
if (!source.field_paragraph_image_image) return {};
if (!imageFile) return {};
return {
fileName: source.field_paragraph_image_image.filename || '',
alt: source.field_paragraph_image_image.alt || '',
title: source.field_paragraph_image_image.title || '',
height: source.field_paragraph_image_image.height,
width: source.field_paragraph_image_image.width,
url: imageFile.uri.url || '',
imageStyleUri: imageFile.image_style_uri
? imageFile.image_style_uri
: '',
};
},
},
imageBis: {
type: 'File',
resolve: (source, args, context) => {
const imageFile = context.nodeModel.getNodeById({
type: 'file__image',
id: source.relationships.field_paragraph_image_image___NODE,
});
if (!source.field_paragraph_image_image) return {};
if (!imageFile) return {};
return {
fileName: source.field_paragraph_image_image.filename || '',
alt: source.field_paragraph_image_image.alt || '',
title: source.field_paragraph_image_image.title || '',
height: source.field_paragraph_image_image.height,
width: source.field_paragraph_image_image.width,
url: imageFile.uri.url || '',
imageStyleUri: imageFile.image_style_uri
? imageFile.image_style_uri
: '',
};
},
},
displayMode: {
type: 'String',
resolve: source => source.field_display_mode || '',
},
},
interfaces: ['Node'],
extensions: {
infer: false,
},
}),
];
Поле, которое я хочу запросить, это “imageBis”, которое является дубликатом “image”, но я изменил тип с “Image” на “File”.
А вот компонент, содержащий мой gql-запрос:
import React from 'react';
import { graphql } from 'gatsby';
import classNames from 'classnames';
import absolutePath from 'utils/absolutePath';
import getTitleNode from 'utils/getters';
import unbreakableSpaceWithPunctuation from 'utils/unbreakableSpaceWithPunctuation';
import * as styles from './paragraphImage.module.css';
type Internal = {
type: string;
};
type Image = {
url: string;
alt: string;
};
type Paragraph = {
drupal_internal__id: number;
internal: Internal;
legend: string;
image: Image;
startPosition: number;
endPosition: number;
displayMode: string;
};
interface Props {
paragraph: Paragraph;
stickyBarLink: string;
}
const ParagraphImage = (props: Props) => {
const paragraphId = props.paragraph.drupal_internal__id;
const classesImage = classNames(styles.img, {
[`${styles.imgCenter}`]: props.paragraph.displayMode === 'center_position',
});
const classesImageContainer = classNames(styles.imgContainer, {
[`${styles.imgContainerCenter}`]:
props.paragraph.displayMode === 'center_position',
});
return (
<div className={styles.alignRight} id={props.stickyBarLink}>
<div id={`summary-start-${paragraphId}`} />
<div className={classesImageContainer}>
<img
className={classesImage}
src={absolutePath(props.paragraph.image.url)}
alt={getTitleNode(props.paragraph.image.alt)}
loading="lazy"
/>
{props.paragraph.legend && (
<legend className={styles.legend}>
{unbreakableSpaceWithPunctuation(props.paragraph.legend)}
</legend>
)}
</div>
<div id={`summary-end-${paragraphId}`} />
</div>
);
};
export const query = graphql`
fragment ParagraphImage on paragraph__image {
drupal_internal__id
internal {
type
}
legend
image {
url
alt
}
imageBis {
publicURL
childImageSharp {
gatsbyImageData
}
}
displayMode
}
`;
export default ParagraphImage;
Я что-то упускаю в запросе?
Большое спасибо за любую помощь.
Ответ или решение
Проблема, с которой вы столкнулись при использовании childImageSharp
с изображениями из Drupal в проекте Gatsby, обусловлена тем, что childImageSharp
ожидает, что переданное изображение будет обработано плагином Sharp. Однако в вашем запросе GraphQL вы получаете изображение, которому не может быть применена обработка, из-за системы типов и отсутствия соответствующих полей в вашем типе данных.
Вот несколько шагов, которые помогут вам решить вашу проблему:
Шаг 1: Проверьте конфигурацию gatsby-source-drupal
Убедитесь, что вы правильно настроили gatsby-source-drupal
и что ваши изображения в Drupal правильно издействованы. Обратите внимание на поля, которые возвращаются вашей API.
Шаг 2: Измените схему
В вашем коде вы определяете поле imageBis
как type: 'File'
. Однако для того, чтобы использовать childImageSharp
, вы должны убедиться, что поле возвращает структуру, которая поддерживает обработку изображений. В идеале ваше поле должно выглядеть как type: 'Image'
, как и поле image
.
Если требуется использовать imageBis
, измените его тип соответствующим образом:
imageBis: {
type: 'Image', // Измените здесь на 'Image'
resolve: (source, args, context) => {
const imageFile = context.nodeModel.getNodeById({
type: 'file__image',
id: source.relationships.field_paragraph_image_image___NODE,
});
if (!source.field_paragraph_image_image) return {};
if (!imageFile) return {};
return {
fileName: source.field_paragraph_image_image.filename || '',
alt: source.field_paragraph_image_image.alt || '',
title: source.field_paragraph_image_image.title || '',
height: source.field_paragraph_image_image.height,
width: source.field_paragraph_image_image.width,
url: imageFile.uri.url || '',
imageStyleUri: imageFile.image_style_uri ? imageFile.image_style_uri : '',
};
},
},
Шаг 3: Обновите ваш запрос GraphQL
Теперь, когда поле имеет правильный тип, убедитесь, что вы правильно вызываете childImageSharp
в вашем запросе GraphQL. Для поля imageBis
, которое вы хотите использовать, измените запрос следующим образом:
export const query = graphql`
fragment ParagraphImage on paragraph__image {
drupal_internal__id
internal {
type
}
legend
image {
url
alt
}
imageBis {
url // Измените publicURL на url, если это изображение
childImageSharp {
gatsbyImageData
}
}
displayMode
}
`;
Шаг 4: Используйте Correct Image Component
Теперь, когда вы извлекаете данные из imageBis
, убедитесь, что вы правильно используете его в компоненте. Вы можете заменить стандартный тег <img>
на компонент GatsbyImage
для работы с изображениями:
import { GatsbyImage } from 'gatsby-plugin-image';
//...
<GatsbyImage
image={props.paragraph.imageBis.childImageSharp.gatsbyImageData}
alt={getTitleNode(props.paragraph.imageBis.alt)}
loading="lazy"
/>
Шаг 5: Тестирование
После всех внесенных изменений убедитесь, что вы перезапустили разработческий сервер (gatsby develop
), и проверьте консоль на наличие ошибок.
Заключение
Если после выполнения всех шагов проблема продолжается, проверьте, действительно ли данные, передаваемые из Drupal, содержат все необходимые поля. Используйте инструменты отладки GraphiQL для проверки возвращаемых данных, чтобы убедиться, что они соответствуют ожидаемым структурами.