Пытаюсь понять как работает этот код, ибо вроде как не должен, но это работает.
Это какая-то магия TypeScript, которую я не понимаю? Реагировать на магию? Как это работает, если регистры — это не строки, а импортированные значения, которые отображаются как undefined
?
import DialogTitle, { DialogTitleProps } from "./Title";
import DialogDescription, { DialogDescriptionProps } from "./Description";
import DialogButton, { DialogButtonProps } from "./Button";
// ....
React.Children.forEach(children, (child) => {
if (typeof child === "object" && child !== null && "type" in child) {
switch (child.type) {
case DialogTitle: // DialogTitle is undefined in the debugger when hovered
titleChildrens.push(child as TitleElement);
return;
case DialogDescription: // DialogDescription is undefined in the debugger when hovered
descriptionChildrens.push(child as DescriptionElement);
return;
case DialogButton: // DialogButton is undefined in the debugger when hovered
if (Platform.OS === "ios" && buttonChildrens.length > 0) {
buttonChildrens.push(
<View
style = {[
verticalButtons
? styles.buttonSeparatorVertical
: styles.buttonSeparatorHorizontal,
buttonSeparatorStyle,
]}
/>
);
}
buttonChildrens.push(child as ButtonElement);
return;
}
}
otherChildrens.push(child);
});
Я думаю, что отладчик вводит вас в заблуждение. Попробуйте добавить оператор console.info(DialogTitle
), и я подозреваю, что вы получите значение, отличное от undefined
.
К сожалению нет. ReferenceError
. Я добавил изображение к вопросу. Вы можете видеть, что case
действительно работает, несмотря на это.
Я имею в виду поместить оператор console.info в код. В консоли работать не будет. Когда вы запускаете console.info(DialogTitle)
в консоли, он пытается сослаться на глобальную переменную с именем DialogTitle
, которой не существует.
Дерп. Попытка это.
Действительно, console.info(DialogTitle)
выводит ƒ
. Но все же, как работает этот оператор switch?
Он проверяет тип ===
функции DialogTitle
(которая была импортирована вверху файла), и если да, то переходит в первый случай. Если нет, он проверяет, является ли тип ===
функцией DialogDescription
, и входит в этот случай. И так далее. Ни одно из значений не является undefined
, каждая из них является независимой функцией, поэтому эта проверка работает нормально и определяет, какой тип компонента был получен (среди ограниченного набора).
Код, который вы видите в отладчике, — это исполняемый код нет. То, что вы видите как Container.tsx
, на самом деле, вероятно, просто фрагмент скомпилированного чистого JS где-то в огромном bundle.js
.
Код машинописного текста требует компиляции, прежде чем браузер сможет его прочитать. В рамках этого шага он также создает исходные карты, которые сопоставляют скомпилированный код с вашими исходными исходными файлами. Webpack или любой другой упаковщик, который вы используете, вероятно, выполняет свою собственную компиляцию и создает новые исходные карты.
По большей части это упрощает отладку, но не идеально. Итак, то, что вы думаете, DialogTitle
, вероятно, является идентификатором, который каким-то образом трансформировался во время компиляции, минимизации, обфускации, связывания и т. д.
Вы можете полностью отключить исходные карты, чтобы получить более четкое представление о том, что происходит, хотя код, который вы отлаживаете, вероятно, начнет выглядеть довольно загадочно.
Исходные карты обычно работают нормально, но я заметил, что не все инструменты могут генерировать их идеально.
Что касается того, как работает оператор switch, у функций есть идентификатор, который может быть запрошен оператором switch.
Например, это работает, потому что MyComponent
присваивается либо A
, либо B
, и каждый case
может проверить это.
function A() { return <>A</> }
function B() { return <>B</> }
const MyComponent = Math.random() > 0.5 ? A : B
switch(MyComponent) {
case A: console.info('got A'); break
case B: console.info('got B'); break
}
// logs "got A" or "got B"
In the code I referenced, it's
switch(child.type)
and I don't understand howchild.type
is compared against a function?child.type
is itself a function, but I'm still very confused about how that comparison evaluates totrue
.
Это немного углубляется во внутренние процессы, поэтому я не могу поручиться за Зачем, но, похоже, это то, что происходит.
Когда компонент визуализируется, он возвращает объект JSX.Element
. Похоже, что этот объект имеет свойство type
, которое является ссылкой на компонент, отрисовывавший этот JSX.
Например:
function A() { return <>A</> }
console.info(<A />);
Выдает это в консоли:
Это означает, что отрендеренный JSX запоминает компонент, который его отрендерил, через это свойство type
. И этот цикл здесь проверяет, были ли какие-либо дочерние элементы визуализированы с определенными компонентами, которые могут нуждаться в специальной обработке.
Вот минимальный пример, это ближе к тому, что на самом деле делает ваш исходный фрагмент.
Вы правы, это, по-видимому, проблема с отображением источника, но не могли бы вы указать мне, как этот тип оператора switch может работать с function
в качестве значения case, и помочь мне получить полный ответ для этого?
У функций есть идентификатор, который может быть проверен оператором switch. Смотрите мое обновление.
Большое спасибо за ваше редактирование! Все это имеет большой смысл, но я все еще застрял на одном моменте. | В коде, на который я ссылался, это switch(child.type)
, и я не понимаю, как child.type
сравнивается с function
? child.type
сама по себе является функцией, но я все еще очень смущен тем, как это сравнение оценивается как true
.
Это основано на том, как реагировать на рендеринг и сериализацию JSX. Он просто ищет JSX, сгенерированный из компонентов, требующих дополнительной обработки. Смотрите мое обновление.
Огромное спасибо за обновление!
Ты не понимаешь. Код рабочий и не мой. Мне нужно понять, что ЗАЧЕМ работает, потому что выглядит так, как будто этого не должно быть, но это так.