JSX: когда оцениваются выражения JavaScript?
После изучения руководств по GatsbyJS и React у меня сложилось впечатление, что выражения JavaScript всегда оцениваются, когда они заключены в {} скобки в JSX. Но теперь я смотрю на файл JSX внутри начального репозитория GatsbyJS, где похоже, что скобки вызывают другое поведение:
const {
data: {
posts: { edges: posts },
site: {
siteMetadata: { facebook }
}
}
} = props;
( Источник)
Согласно учебным пособиям, "facebook" должен оцениваться как JavaScript и должен возвращать undefined, но это не то, что происходит. Каким-то образом мы получаем объект JavaScript data.site.siteMetadata.facebook, в котором есть некоторые данные. Что тут происходит? Почему "facebook" не оценивается как выражение JavaScript?
1 ответ
Кусок кода, который вы копируете, на самом деле не имеет ничего общего с JSX (см. Ниже). Это синтаксис деструктуризации объекта ES6, как прокомментировал вопрос @PrithvirajSahu.
Скажем, у вас есть такой объект:
const obj = {
a: 100,
b: {
value: 200,
}
};
Вы можете получить внутренние значения так:
const { a } = obj;
// same as const a = obj.a
const { b: c } = obj;
// same as const c = obj.b
const { b: { value } } = obj;
// same as const value = obj.b.value
const { b: { value: v } } = obj;
// same as const v = obj.b.value
const { a, { b: { value } } } = obj;
// same as
// const a = obj.a;
// const value = obj.b.value;
Итак, вернемся к вашему коду, это эквивалентно
const posts = props.data.posts.edges;
const facebook = props.data.site.siteMetadata.facebook;
Как вы выяснили, синтаксис деструктурирования очень аккуратен на 1 или 2 уровнях, но его трудно прочитать, когда их больше. Лично я использую его только на 1 уровне.
Изменить: в функции в источнике, только строки, начинающиеся с <...
такое синтаксис JSX
const CategoryPage = props => {
// code here is normal js
const { ... } = props;
// JSX start from inside this return function
return (
<React.Fragment>
{ /* code between bracket in this section will be evaluate as 'normal JS' */ }
</React.Fragment>
)
}
Предостережение: код в скобках в JSX должен вычислять функцию. Если мы напишем что-то вроде этого:
<div className="container">
Hello
{"Happy"}
World
</div>
Бабель превратит это в следующий регулярный JS:
React.createElement(
"div",
{ className: "container" },
"Hello",
"Happy",
"World"
);
Все, что мы поместим между скобками, будет передано React.createElement
как дитя div
элемент; поэтому только действительный элемент React может быть размещен здесь:
- Null (ничего не делать)
- Строка (станет текстовым узлом DOM)
- Еще один элемент React
- Выражение / функция, которая оценивает или возвращает любое из вышеперечисленного
<div>
{ hasDate && <Date /> }
<div>
или же
// somewhere in the code
const showDate = (hasDate) => {
if (!hasDate) return null;
return <Date />
}
// in the render function
return (
<div>
{ showDate(hasDate) }
<div>
)
Мы также можем использовать скобку, чтобы передать значение реквизиту элемента:
<div
style={ { color: 'red' } }
onClick={ (event) => {...} }>
{ hasDate && <Date /> }
<div>