Правка 3: Что меня смущает, так как неизвестность, которую я не вижу в документации, - это то, как она работает. IE, как работают дети. Мне кажется, что вы бросаете обещание, глядя на код демонстрации в документации. Но я нигде не вижу этого документированного.
Таким образом, вы бросаете обещание, что после разрешения ваш компонент теперь готов (ie. Обещание таймера - или обещание клиента Apollo - получите обещание и т. Д. c.). Когда это обещание разрешится, ваш компонент сможет подключиться. Мне это нравится, я sh это было четко задокументировано, если я правильно понял, как это работает.
Эта проблема не имеет ничего общего с неизвестностью. Ваш код:
const Hallo = () => {
const [text, setText] = useState("your on time");
useEffect(
// setText(
// wrapPromise(lazyTimer()).read()
// ), [text],
// );
return <h2>hello world, {text}</h2>;
};
Имеет эту проблему. Он запускает setText
, затем имеет text
в качестве зависимости. Таким образом, вы меняете text
, затем он запускается снова, потому что text
меняется. Следовательно, бесконечное l oop.
У вас есть 3 способа исправить это
1) Сделайте какое-нибудь утверждение if
, чтобы сделать его не бесконечным l oop (ie). Вы знаете, какой текст не должен быть, или проверьте, совпадает ли он).
2) Удалите text
из списка зависимостей (плохо!)
3) удалите его, используя альтернативный метод setText
, вызывающий его как функцию вместо предоставления значения. См. здесь для документации.
useEffect(
setText(text => wrapPromise(lazyTimer()).read())
), [],
);
, тогда text
не будет зависимостью.
Я рекомендую 3.
Редактировать :
Кроме того, вы использовали оболочку неправильно. Я посмотрел учебник 1038 *, который вы, вероятно, использовали, и его Github . Они создают обертку. Затем в части извлечения данных (ваш таймер) оберните их обещание в оболочку обещаний.
Я попытался сохранить ваш код максимально похожим, используя useEffect
:
import React, { Suspense, useEffect, useState } from "react";
import "./styles.css";
const wrapPromise = promise => {
let status = "pending";
let result;
console.log(`looping.... + ${new Date().toString()}`);
const suspender = promise.then(
r => {
status = "fulfilled";
result = r;
},
e => {
status = "rejected";
result = e;
}
);
const read = () => {
if (status === "pending") {
throw suspender;
} else if (status === "rejected") {
throw result;
} else {
return result;
}
};
return { read };
};
const lazyTimer = () => {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(" from 10sec past");
}, 10000);
});
return wrapPromise(promise);
};
const data = lazyTimer();
const Hallo = () => {
const [text, setText] = useState(data.read());
useEffect(() => {
console.log("Im running");
setText(data.read());
}, []);
return <h2>hello world, {text}</h2>;
};
export default function App() {
return (
<div className="App">
<Suspense fallback={<p>Loading...</p>}>
<Hallo />
</Suspense>
</div>
);
}
Это работает , Песочница здесь .
Следует отметить, что ореол может быть просто:
const Hallo = () => {
const text = data.read()
return <h2>hello world, {text}</h2>;
};