Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Загрузка данных из API

Настоящие приложения берут данные с сервера. В React Native доступна та же функция fetch, что и в браузере, а запрос, как и в вебе, отправляют в useEffect. На телефоне добавляются свои детали: системный индикатор загрузки и обновление списка жестом «потянуть вниз».

Список статей

Адрес https://jsonplaceholder.typicode.com/posts возвращает 100 статей с полями id, title, body. Замените локальный массив загрузкой в app/(tabs)/index.tsx:

// app/(tabs)/index.tsx
import { Link } from 'expo-router';
import { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
import type { Post } from '@/data/posts';
 
const API = 'https://jsonplaceholder.typicode.com';
 
export default function Posts() {
  const [posts, setPosts] = useState<Post[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
 
  async function load() {
    setLoading(true);
    setError(null);
    try {
      const response = await fetch(`${API}/posts`);
      if (!response.ok) throw new Error(`Ошибка ${response.status}`);
      setPosts(await response.json());
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Неизвестная ошибка');
    } finally {
      setLoading(false);
    }
  }
 
  useEffect(() => {
    load();
  }, []);
 
  if (loading && posts.length === 0) {
    return <ActivityIndicator size="large" style={{ flex: 1 }} />;
  }
 
  if (error) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', gap: 12 }}>
        <Text>Не удалось загрузить статьи: {error}</Text>
        <Text onPress={load} style={{ color: '#2563eb' }}>Повторить</Text>
      </View>
    );
  }
 
  return (
    <FlatList
      data={posts}
      keyExtractor={(item) => String(item.id)}
      refreshing={loading}
      onRefresh={load}
      renderItem={({ item }) => (
        <Link href={{ pathname: '/posts/[id]', params: { id: item.id } }} style={{ padding: 16 }}>
          {item.title}
        </Link>
      )}
    />
  );
}

Сначала по центру крутится системный индикатор ActivityIndicator, затем появляется список из 100 заголовков. Тип Post по-прежнему берётся из data/posts.ts.

Обновление жестом

Пропсы refreshing и onRefresh включают у FlatList обновление жестом: потяните список вниз — появится индикатор, и load загрузит статьи заново. Пока refreshing равен true, индикатор крутится.

Ошибка и повтор

Включите режим полёта и перезапустите приложение клавишей r — вместо списка появится сообщение об ошибке. Выключите режим полёта и нажмите «Повторить»: статьи загрузятся. На телефоне связь пропадает часто, поэтому кнопка повтора нужна почти всегда.

Экран статьи

Экран app/posts/[id].tsx загружает одну статью по адресу ${API}/posts/${id} тем же способом: состояние post, loading, error и useEffect с зависимостью [id]. Комментарии к статье лежат по адресу /posts/1/comments.

Частая ошибка

Обращаться к localhost с телефона. Если вы запустили свой API на компьютере по адресу http://localhost:3000, то на телефоне localhost — это сам телефон, и запрос не дойдёт. Используйте IP-адрес компьютера в локальной сети, например http://192.168.1.10:3000. Кроме того, iOS по умолчанию блокирует запросы по http, поэтому для настоящего сервера нужен https.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.