برنامه نویسی

چگونه یک شبکه اجتماعی در 1 روز بسازیم: قسمت 6 – افزودن یک فید

در فصل قبلی این آموزش، ویژگی Create Post را زنده کردیم. این شامل ساخت مولفه هایی برای درخواست مجوز دوربین، گرفتن یا انتخاب تصاویر، پیش نمایش عکس ها و نهایی کردن پست ها با شرح بود. برای اطمینان از عملکرد بهتر، ما همچنین یک تابع ابزار تغییر اندازه تصویر را معرفی کردیم که مدیریت فایل‌های بزرگ‌تر را ساده‌تر می‌کرد.

اکنون، با قابلیت ایجاد پست در محل، زمان آن رسیده است که راهی برای مشاهده محتوای خود به کاربران ارائه دهیم. در این فصل، ما بر ایجاد پایه فید تمرکز خواهیم کرد، جایی که پست ها نمایش داده می شوند. این شامل طراحی رابط کاربری برای ظاهر یک پست است که با دکمه هایی برای لایک، نظرات، نشانک ها و آواتارهای کاربر تکمیل می شود. در پایان این بخش، کاربران می‌توانند پست‌هایی را که ایجاد کرده‌اند در یک رابط فید کاربردی و جذاب بصری مرور کنند.

توجه به این نکته مهم است که اگرچه ما این دکمه‌های تعاملی را به رابط کاربری پست اضافه می‌کنیم، اما هنوز به هیچ عملکردی متصل نمی‌شوند. زمانی که ویژگی‌هایی مانند لایک‌ها، نظرات و نشانک‌ها را پیاده‌سازی کنیم، در فصل‌های بعدی خواهد آمد. در حال حاضر، تمرکز بر بسترسازی و قرار دادن عناصر بصری در جای خود است.

زمان انباشته مطالعه تاکنون: 30 دقیقه.

قسمت 6 برای مرجع در GitHub مخزن کامل شد

به روز رسانی صفحه اصلی

قبل از به روز رسانی Home صفحه نمایش با عملکرد خوراک، حفظ هر گونه عملکرد موجود مهم است. اگر جریان شما Home صفحه نمایش شامل دکمه هایی برای ورود و خروج از برنامه است، آن عملکرد را به برنامه منتقل کنید Profile صفحه نمایش (app/(tabs)/profile/index.tsx). این تضمین می‌کند که هنگام انتقال، ویژگی‌های ورود و خروج در دسترس باقی می‌مانند Home صفحه نمایش به یک فید

برای انجام این کار:

  1. را باز کنید app/(tabs)/index.tsx کد موجود برای دکمه‌های ورود و خروج را فایل کنید و پیدا کنید.

  2. این کد را برش داده و در آن قرار دهید app/(tabs)/profile/index.tsx.

هنگامی که این قابلیت را منتقل کردید، آماده جایگزینی کد موجود در آن هستید Home صفحه نمایش با موارد زیر:

import React from "react";
import { FeedProvider } from "replyke-expo";
import Feed from "../../components/home/Feed";

const Home = () => {
  return (
    <FeedProvider sortBy="hot">
      <Feed />
    FeedProvider>
  );
};

export default Home;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این کد جدید چه می کند

  1. ارائه دهنده خوراک: این یک ارائه‌دهنده زمینه است که به همه مؤلفه‌های فرزند خود امکان دسترسی به داده‌ها و عملکرد فید را می‌دهد. ما تنظیم کرده ایم sortBy prop to “hot” که به این معنی است که “گرم ترین” پست ها در فید ما بالاتر ظاهر می شوند. سیستم امتیازدهی برای «داغ» به‌طور خودکار توسط Replyke مدیریت می‌شود، بنابراین نیازی نیست خودتان نگران پیاده‌سازی آن باشید.

  2. خوراک: این مؤلفه رابط کاربری فید را مدیریت می کند. از الف استفاده خواهد کرد FlatList برای ارائه پست های تکی که در مراحل بعدی اجرا خواهیم کرد.

با انتقال عملکرد ورود و خروج به سیستم Profile صفحه نمایش و به روز رسانی Home صفحه، شما زمینه را برای ساختن رابط کاربری فید آماده کرده اید. بیایید به اجرای آن ادامه دهیم Feed جزء بعدی!

ایجاد مؤلفه فید

بعد، بیایید ایجاد کنیم Feed جزء با ایجاد یک پوشه جدید به نام شروع کنید home داخل app/components دایرکتوری در این پوشه، یک فایل جدید به نام ایجاد کنید Feed.tsx.

در اینجا محتوایی برای Feed.tsx فایل:

import React, { useCallback, useState } from "react";
import { EntityProvider, useFeed } from "replyke-expo";
import {
  RefreshControl,
  View,
  Text,
  FlatList,
  ActivityIndicator,
} from "react-native";
import { SinglePost } from "../shared/SinglePost";

function Feed() {
  const { entities, loadMore, resetEntities, loading } = useFeed();
  const [listHeight, setListHeight] = useState(0);
  const [refreshing, setRefreshing] = useState(false);

  const onRefresh = useCallback(async () => {
    setRefreshing(true);
    await resetEntities?.();
    setRefreshing(false);
  }, [resetEntities]);

  const initialLoading = loading && (!entities || entities.length === 0);

  if (initialLoading)
    return (
      <View className="flex-1 items-center justify-center">
        <ActivityIndicator size="large" />
      View>
    );

  return (
    <View
      className="flex-1"
      onLayout={(event) => {
        if (event.nativeEvent.layout.height > listHeight)
          setListHeight(event.nativeEvent.layout.height);
      }}
    >
      <FlatList
        data={entities!}
        renderItem={({ item: entity }) => (
          <EntityProvider entity={entity}>
            <SinglePost listHeight={listHeight} />
          EntityProvider>
        )}
        keyExtractor={(item) => item.id}
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
        }
        onEndReached={loadMore}
        onEndReachedThreshold={2}
        ListFooterComponent={null}
        ListEmptyComponent={
          loading ? null : (
            <View
              className="flex-1 bg-white justify-center"
              style={{
                height: listHeight,
              }}
            >
              <Text className="text-center text-xl font-medium text-gray-400">
                No Results
              Text>
              <Text className="text-center text-lg text-gray-400 mt-2">
                Try expanding your search
              Text>
            View>
          )
        }
        pagingEnabled
        decelerationRate="fast"
        showsVerticalScrollIndicator={false}
        snapToAlignment="start"
        scrollEventThrottle={16}
        bounces={false}
      />
    View>
  );
}

export default Feed;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مؤلفه فید چه اتفاقی می افتد

  • استفاده از فید هوک: این قلاب سفارشی از replyke-expo داده‌های فید، از جمله وضعیت‌های بارگیری، موجودیت‌ها (پست‌ها) و عملکرد صفحه‌بندی را واکشی و مدیریت می‌کند.

  • مدیریت دولتی: استفاده می کنیم useState برای مدیریت:

    • listHeight: ارتفاع لیست را برای اطمینان از رندر مناسب پیگیری می کند.
    • refreshing: وضعیت کشش برای تازه کردن را ردیابی می کند.
  • کشش برای تازه کردن: onRefresh تابع با فراخوانی داده های فید را بازنشانی می کند resetEntities. این یک تجربه کاربری روان برای تازه کردن فید فراهم می کند.

  • پارامترهای FlatList:

    • data: این آرایه ای از پست ها (موجودات) برای نمایش در فید است.
    • renderItem: برای هر مورد (پست) در data، این یک را ارائه می دهد SinglePost جزء پیچیده شده در یک EntityProvider، که زمینه لازم را برای پست فراهم می کند.
    • keyExtractor: برای هر مورد بر اساس آن یک کلید منحصر به فرد ایجاد می کند id دارایی
    • refreshControl: قابلیت کشش برای تازه کردن را با a فعال می کند RefreshControl جزء
    • onEndReached: هنگامی که کاربر نزدیک به انتهای لیست پیمایش می کند و تماس می گیرد فعال می شود loadMore برای دریافت پست های اضافی
    • onEndReachedThreshold: تعیین می کند که کاربر چقدر باید به پایین اسکرول کند onEndReached to trigger (2 به این معنی است که عملکرد کمی زودتر فعال می شود).
    • ListEmptyComponent: زمانی که هیچ پستی برای نمایش وجود ندارد و بارگیری انجام نمی شود پیامی را نمایش می دهد.
    • pagingEnabled: اطمینان می دهد که پیمایش به موارد می چسبد.
    • decelerationRate و snapToAlignment: به ایجاد یک تجربه پیمایش روان و سریع کمک کنید.
    • showsVerticalScrollIndicator: نشانگر اسکرول را پنهان می کند.
    • scrollEventThrottle: فرکانس رویدادهای اسکرول را برای عملکرد بهتر کنترل می کند.
    • bounces: جلوه پرش را هنگام پیمایش از لبه های لیست غیرفعال می کند.
  • ایالات در حال بارگذاری:

    • یک را نمایش می دهد ActivityIndicator در حالی که داده های اولیه در حال بارگیری هستند.

این تنظیمات تضمین می‌کند که فید به صورت پویا صفحه‌بندی، تازه‌سازی و حالت‌های خالی را مدیریت می‌کند و تجربه کاربری یکپارچه را ایجاد می‌کند. در مرحله بعد، ما آن را اجرا می کنیم SinglePost جزء برای تکمیل نمایش پست!

پیاده سازی کامپوننت SinglePost

پوشه و ساختار فایل

بیایید خودمان را سازماندهی کنیم SinglePost جزء برای استفاده مجدد در چندین صفحه (به عنوان مثال، صفحه اصلی، نمایه کاربر، یک پست). ساختار زیر را در داخل ایجاد کنید app/components:

app/
  components/
    shared/
      SinglePost/
        SinglePost.tsx
        PostActions.tsx
        index.ts
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما قرار می دهیم SinglePost در shared پوشه زیرا در چندین صفحه استفاده مجدد خواهد شد. ایجاد یک پوشه اختصاصی برای SinglePost قطعات مرتبط را به طور مرتب سازماندهی می کند، زیرا این جزء در طول زمان پیچیدگی بیشتری پیدا می کند.

SinglePost.tsx

ایجاد کنید SinglePost.tsx فایل با کد زیر:

import { Image, Text, View } from "react-native";
import React from "react";
import { useEntity } from "replyke-expo";
import PostActions from "./PostActions";

const SinglePost = ({ listHeight }: { listHeight: number }) => {
  const { entity } = useEntity();

  if (!entity) return null; // This ensures type safety, as the EntityProvider guarantees entity existence.

  return (
    
      

      {/* Caption */}
      
        {entity.title}
      

      {/* Actions */}
      
    
  );
};

export default SinglePost;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیح:

  • بافت موجودیت: useEntity هوک داده های پست فعلی (موجود) را ارائه می دهد. اگر هیچ موجودی در دسترس نباشد، مؤلفه چیزی را ارائه نمی‌کند. این امر ایمنی نوع را تضمین می کند EntityProvider به طور مستقیم تعریف شده را می گذراند entity.

  • نمایش تصویر: رسانه اصلی پست (تصویر) به صورت تمام صفحه نمایش داده می شود.

  • عنوان: عنوان پست به صورت همپوشانی در پایین تصویر ظاهر می شود.

  • PostActions: دکمه هایی را برای تعامل با پست اضافه می کند، مانند لایک ها، نظرات و نشانک ها.

PostActions.tsx

ایجاد کنید PostActions.tsx فایل با کد زیر:

import React from "react";
import { View, TouchableOpacity, Text, Pressable } from "react-native";
import { useEntity, UserAvatar } from "replyke-expo";
import FontAwesome from "@expo/vector-icons/FontAwesome";
import AntDesign from "@expo/vector-icons/AntDesign";
import Ionicons from "@expo/vector-icons/Ionicons";

function PostActions() {
  const { entity } = useEntity();

  if (!entity) return null;

  return (
    
      {/* User avatar and follow button */}
      
        
      

      {/* LIKE BUTTON */}
      
        

        
          {entity?.upvotes.length}
        
      

      {/* OPEN COMMENT SECTION */}
      
        

        {(entity.repliesCount || 0) > 0 && (
          {entity.repliesCount}
        )}
      

      {/* BOOKMARK BUTTON */}
      
        
      
    
  );
}

export default PostActions;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیح:

  • آواتار کاربر: آواتار سازنده پست را نمایش می دهد. در آینده، با ضربه زدن روی آن می‌توانید به نمایه کاربر پیمایش کنید.

  • مانند دکمه: تعداد لایک/رای مثبتی که پست دریافت کرده را نشان می دهد. این دکمه بعداً از لایک کردن/لیک کردن پست ها پشتیبانی می کند.

  • دکمه نظر: تعداد نظرات (در صورت وجود) را نشان می دهد. این دکمه بعداً با کلیک کردن، بخش نظرات را باز می کند.

  • دکمه نشانک: اجازه ذخیره پست را می دهد. این دکمه بعداً برگه مجموعه ها را باز می کند.

index.ts

ایجاد کنید index.ts فایل با موارد زیر:

export { default as SinglePost } from "./SinglePost";
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این اجازه می دهد تا اجزای دیگر وارد شوند SinglePost به راحتی از پوشه

بسته بندی

در این فصل، ما زمینه را برای فید با ایجاد آن فراهم کرده‌ایم Feed و SinglePost اجزاء این مؤلفه‌ها نمایش پست‌ها را در یک طرح‌بندی بصری جذاب و تعاملی، از جمله ویژگی‌هایی مانند لایک، نظرات و نشانک‌ها انجام می‌دهند. در حالی که ما پایه را ساخته ایم، هنوز کارمان تمام نشده است! در فصل بعدی، ما این ویژگی‌ها را سیم‌کشی می‌کنیم تا کاملاً کاربردی باشند و به کاربران این امکان را می‌دهند که به طور یکپارچه با محتوا درگیر شوند.

به روز بمانید

فراموش نکنید که به سرور Discord بپیوندید، جایی که من مخازن رایگان کد boilerplate را برای انواع مختلف شبکه های اجتماعی ارسال می کنم. به‌روزرسانی‌های مقاله بعدی و منابع اضافی نیز در آنجا به اشتراک گذاشته خواهد شد. در نهایت، من را برای به روز رسانی در اینجا و در X/Twitter و BlueSky دنبال کنید.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا