Биндинги фреймворков
Query реализует протокол effector @@unitShape, поэтому его можно передать прямо в useUnit из effector-react, effector-vue или effector-solid — без обёрток.
// React
import { useUnit } from 'effector-react';
function UserCard({ id }: { id: number }) {
const { data, pending, error, refetch } = useUnit(userQuery);
return pending ? <Spinner /> : <div onClick={() => refetch(id)}>{data?.name}</div>;
}<!-- Vue -->
<script setup lang="ts">
import { useUnit } from 'effector-vue/composition';
const { data, pending, refetch } = useUnit(userQuery);
</script>useUnit(query) отдаёт { data, error, status, pending, stale, enabled, params, start, refetch, refresh, reset, cancel }.
Хелперы useQuery
Тонкие хелперы с производными флагами (isInitial / isPending / isDone / isFail):
// React — effector-refetch/react
import { useQuery } from 'effector-refetch/react';
const { data, isPending, isFail, error, start } = useQuery(userQuery);
useEffect(() => start(id), [id]); // запросы не стартуют сами<!-- Vue — effector-refetch/vue (возвращает ref-ы) -->
<script setup lang="ts">
import { useQuery } from 'effector-refetch/vue';
const { data, isPending, isDone, start } = useQuery(userQuery);
</script>// Solid — effector-refetch/solid (возвращает accessor-ы — вызывайте их)
import { useQuery } from 'effector-refetch/solid';
function UserCard(props: { id: number }) {
const { data, isPending, isFail, start } = useQuery(userQuery);
start(props.id); // запросы не стартуют сами
return <div>{isPending() ? 'Loading…' : data()?.name}</div>;
}React работает с <Provider value={scope}>, Vue — с EffectorScopePlugin, Solid — с <Provider> из effector-solid; всё для SSR / fork. Биндинги требуют соответствующих опциональных peer-зависимостей (react+effector-react / vue+effector-vue / solid-js+effector-solid).
Рефетч на маунте
useQuery (во всех трёх фреймворках) принимает объект опций — refetchOnMount перезапрашивает запрос с его последними параметрами, когда компонент подписывается:
useQuery(userQuery, { refetchOnMount: true }); // рефетч только если данные устарели
useQuery(userQuery, { refetchOnMount: 'always' }); // рефетч на каждом маунтеNo-op, пока запрос не запускался хотя бы раз (status !== 'initial') и включён — он никогда не стартует запрос без параметров. true требует cache.staleAfter, чтобы было понятие устаревания; 'always' его игнорирует.
Suspense (React)
useSuspenseQuery возвращает данные напрямую (никогда не null): он сам стартует запрос, подвешивает ближайший <Suspense> на время загрузки, бросает ошибку в ближайший Error Boundary при сбое и возвращает данные по готовности.
import { Suspense } from 'react';
import { useSuspenseQuery } from 'effector-refetch/react';
function UserName({ id }: { id: number }) {
const user = useSuspenseQuery(userQuery, id); // подвешивается до готовности
return <span>{user.name}</span>;
}
function Page({ id }: { id: number }) {
return (
<ErrorBoundary fallback={<p>Не удалось загрузить</p>}>
<Suspense fallback={<Spinner />}>
<UserName id={id} />
</Suspense>
</ErrorBoundary>
);
}Это клиентский Suspense: чтение и триггеры учитывают scope, но сигнал завершения наблюдается глобально — используйте с fork вне конкурентного SSR-стриминга.