You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Supabase与Next.js实现房产列表筛选按钮的技术求助

基于Supabase与Next.js实现房产列表筛选按钮的技术求助

嘿,刚接触Next.js和Web开发的话,能搭到这个框架已经很棒啦!看你给出的代码,已经有了filter状态,应该是想给房产列表加筛选功能对吧?我来帮你梳理下实现思路和代码完善方案~

方案一:后端筛选(推荐,数据量大时更高效)

直接让Supabase根据筛选条件返回对应数据,避免前端加载全部数据再过滤,性能更优:

const Properties = () => {
    const [user, setUser] = useState();
    const [filter, setFilter] = useState('');
    const [properties, setProperties] = useState<Property[]>([]);
    
    useEffect (() => {
        // 检查用户登录状态,未登录则跳转登录页
        const checkAuthAndFetchProperties = async () => {
            const { data: { user } } = await supabase.auth.getUser();
            if (!user) {
                redirect('/login');
                return;
            }
            setUser(user);
            
            // 根据筛选条件构建Supabase查询语句
            let query = supabase.from('properties').select('*');
            
            // 按空置状态筛选的核心逻辑,可按需扩展
            if (filter === 'vacant') {
                query = query.eq('vacant', true);
            } else if (filter === 'occupied') {
                query = query.eq('vacant', false);
            }
            // 示例:添加租金范围筛选
            // if (filter.rentMin) query = query.gte('rent_per_month', filter.rentMin);
            
            const { data, error } = await query;
            if (error) {
                console.error('加载房产数据失败:', error);
                // 这里可以加用户友好提示,比如Toast组件
                return;
            }
            setProperties(data as Property[]);
        };

        checkAuthAndFetchProperties();
    }, [filter]); // 依赖filter,筛选条件变化时自动重新查询

    return (
        <div className="properties-page">
            <Sidebar />
            <div className="main-content">
                <PageHeader title={pageTitle} />
                {/* 筛选按钮组 */}
                <div className="filter-controls">
                    <button 
                        onClick={() => setFilter('')}
                        className={filter === '' ? 'active-filter' : ''}
                    >
                        全部房源
                    </button>
                    <button 
                        onClick={() => setFilter('vacant')}
                        className={filter === 'vacant' ? 'active-filter' : ''}
                    >
                        空置房源
                    </button>
                    <button 
                        onClick={() => setFilter('occupied')}
                        className={filter === 'occupied' ? 'active-filter' : ''}
                    >
                        已出租房源
                    </button>
                </div>
                <PropertyList properties={properties} />
            </div>
        </div>
    );
};

export default Properties;

方案二:前端筛选(适合数据量小的场景)

如果你的房产数据量不大,也可以先加载全部数据,再在前端用数组方法过滤,减少后端请求次数:

import { useEffect, useState, useMemo } from 'react';
// 其他导入保持不变

const Properties = () => {
    const [user, setUser] = useState();
    const [filter, setFilter] = useState('');
    const [allProperties, setAllProperties] = useState<Property[]>([]);
    
    useEffect (() => {
        // 仅在组件挂载时加载全部数据
        const checkAuthAndFetchAllProperties = async () => {
            const { data: { user } } = await supabase.auth.getUser();
            if (!user) {
                redirect('/login');
                return;
            }
            setUser(user);
            
            const { data, error } = await supabase.from('properties').select('*');
            if (error) {
                console.error('加载房产数据失败:', error);
                return;
            }
            setAllProperties(data as Property[]);
        };

        checkAuthAndFetchAllProperties();
    }, []);

    // 用useMemo避免不必要的重渲染,仅当数据或筛选条件变化时计算
    const filteredProperties = useMemo(() => {
        if (!filter) return allProperties;
        switch(filter) {
            case 'vacant':
                return allProperties.filter(p => p.vacant);
            case 'occupied':
                return allProperties.filter(p => !p.vacant);
            // 示例:按高租金筛选
            // case 'high-rent':
            //     return allProperties.filter(p => p.rent_per_month > 2000);
            default:
                return allProperties;
        }
    }, [allProperties, filter]);

    return (
        <div className="properties-page">
            <Sidebar />
            <div className="main-content">
                <PageHeader title={pageTitle} />
                {/* 筛选按钮组和方案一一致 */}
                <div className="filter-controls">
                    {/* 按钮代码省略 */}
                </div>
                <PropertyList properties={filteredProperties} />
            </div>
        </div>
    );
};

实用小建议

  • 给筛选按钮加active-filter类,用CSS高亮当前选中的筛选条件,提升用户体验
  • 如果需要更复杂的筛选(比如地址搜索、租金滑块),可以把filter改成对象类型,比如const [filter, setFilter] = useState({ vacant: null, minRent: 0 }),再对应调整查询逻辑
  • 错误处理别只停留在控制台打印,给用户显示友好的提示信息会更专业

备注:内容来源于stack exchange,提问作者Harvey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 08:53:03