home 页面有时可以渲染,有时没有渲染,空白的,请求是正常的

来源:21-2 实战仿写小红书App-实现列表显示和分页加载

西瓜一号

2024-07-18

import { observable } from "mobx";
import apiConfig from "../../api/Apis";
import { request } from "../../utils/request"


const SIZE = 10;
export default class HomeStore {

    page: number = 1;
    @observable homeList: ArticleSimple[] = []; //@observable 装饰器,homeList变化会引起UI刷新的

    @observable refreshing:boolean = false;
    setPage = () => {
        this.page = 1;
        // this.requesHomeList();
    }

    requesHomeList = async () => {
        if(this.refreshing === true){
            return; //正在请求,不可以再次请求
        }
        try {
            this.refreshing = true;
            const params = {
                page: this.page,
                size: SIZE,
            };

            const { data } = await request(apiConfig.homeList.name, params);
            console.log(data);
            this.homeList = data;
            if (data?.length){
                // 有数据
                if(this.page === 1){
                    this.homeList = data;
                }else{
                    this.homeList = [...this.homeList,...data];
                }
                this.page = this.page + 1;
            }else{
                //无数据
                if(this.page === 1){
                    this.homeList = [];
                }else{
                    //已经加载完了,没有新数据了
                    console.log('已经加载完了,没有新数据了');
                }
            }
        } catch (error) {
            console.error(error);
        } finally{
            this.refreshing = false;
        }
    }
}
import React, { useEffect } from "react";
import { View, Text, StyleSheet, FlatList, Dimensions, Image } from "react-native";
import { observer, useLocalStore } from "mobx-react";
import { useLocalObservable } from 'mobx-react-lite';
import HomeStore from "./HomeStore";
import { TouchableOpacity } from "react-native-gesture-handler";


import icon_heart_empty from '../../assets/icon_heart_empty.png'
import icon_heart from '../../assets/icon_heart.png'

export default observer(() => {

    const { width: SCREEN_WIDTH } = Dimensions.get('window')

    // const store = useLocalObservable(() => new HomeStore());
    const store = useLocalStore(() => new HomeStore());

    useEffect(() => {
        store.requesHomeList();
    }, []);

    const refreshNewData = () =>{
        store.setPage();
        store.requesHomeList();
        console.log('refreshNewData')
    }

    const loadMoreData = () =>{
        store.requesHomeList();
        console.log('loadMoreData')
    }


    const renderItem = ({ item, index }: { item: ArticleSimple, index: number }) => {

        const s = StyleSheet.create({
            root: {
                flexDirection: 'column',
                width: SCREEN_WIDTH - 18 >> 1,
                backgroundColor: 'white',
                marginLeft: 6,
                marginBottom: 6,
                // height:260,
                borderRadius:8,
                overflow:'hidden' //子组件超出范围隐藏
            },
            img: {
                width: '100%',
                height: 240,
                resizeMode: 'cover',
            },
            content: {
                fontSize: 14,
                fontWeight: 'bold',
                color: '#333',
                marginVertical:4,
                marginHorizontal:12

            },
            layoutView: {
                flexDirection: 'row',
                width: '100%',
                height: 40,
                alignItems: 'center',
                // backgroundColor: 'pink',
                paddingHorizontal: 10,
                marginBottom:10,
            },
            avatar: {
                width: 20,
                height: 20,
                resizeMode: 'contain',
                borderRadius: 10,
            },
            userName: {
                fontSize: 12,
                color: '#999',
                flex: 1,
                marginLeft:6
            },

            favoriteCount: {
                fontSize: 14,
                color: '#999',
                marginLeft:4
            },
            favoriteButton: {

            },
            favoriteImg: {
                width: 20,
                height: 20,
                resizeMode:'contain',
            }
        });
        return (
            <View style={s.root}>
                <Image style={s.img} source={{ uri: item.image }} />
                <Text style={s.content}>{item.title}</Text>
                <View style={s.layoutView}>
                    <Image style={s.avatar} source={{ uri: item.avatarUrl }} />
                    <Text style={s.userName}>{item.userName}</Text>
                    <TouchableOpacity style={s.favoriteButton}>
                        <Image style={s.favoriteImg} source={item.isFavorite ? icon_heart : icon_heart_empty} />
                    </TouchableOpacity>
                    <Text style={s.favoriteCount}>{item.favoriteCount}</Text>

                </View>
            </View>
        );
    };

    const Footer = () => {
        return (
            <Text style={s.footer}>
                没有数据了
            </Text>
        );
    };
    return (
        <View style={s.root}>

            <FlatList
                style={s.flatList}
                contentContainerStyle={s.contentContainerStyle}
                data={store.homeList}
                extraData={[store.refreshing]}
                renderItem={renderItem}
                numColumns={2}
                refreshing={store.refreshing}
                onRefresh={refreshNewData}
                // keyExtractor={(item, index) => `${index} - ${item.title}`}
                onEndReachedThreshold={0.1}
                onEndReached={loadMoreData}
                ListFooterComponent={<Footer />}
                
            />

        </View>
    );
});

const s = StyleSheet.create({
    root: {
        width: '100%',
        height: '100%',
        backgroundColor: '#f0f0f0',
        flexDirection: 'column',

        justifyContent: 'center',
        alignItems: 'center',
    },

    flatList: {
        width: '100%',
        height: '100%',
    },
    contentContainerStyle:{
        paddingTop:6,
    },

    footer:{
        width:'100%',
        fontSize:14,
        color:'#999',
        marginVertical:12,
        textAlign:'center',
        textAlignVertical:'center',
    },
});

图片描述

还有上拉加载更多请求数据有了,不能刷新UI

图片描述

多次测试发现,没有观察到store的数据变化,导致没有刷新UI,要是store.homeList初始化写死数据,渲染是正常的,在store里面打印homeList也是有数据的,就是在home页面没法触发渲染

写回答

1回答

FE大公爵

2025-04-22

看了代码,可能有两个原因。你分别试一下。

1、你集成的是新版本mobx,但是代码用的还是老的api,你尝试用新版api看看。

2、你的store里,在接口返回数据时,多写了一个this.homeList=data,把这个去掉,下面有针对分页的赋值处理。

0
0

RN从0到1系统精讲与小红书APP实战

30+小案例+2个实战项目,快人一步提升个职业竞争力

295 学习 · 211 问题

查看课程