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

React结合JSON Server实现免登录看首页、登录获全权限方案问询

实现React+JSON Server的登录权限控制(游客/登录用户区分操作)

需求说明

  • 游客模式:无需登录即可进入首页查看posts,但无法执行添加、编辑、删除操作
  • 登录模式:用户登录后返回首页,拥有全部操作权限
  • 技术栈:React + JSON Server

解决方案步骤

1. 完善登录状态持久化逻辑

修改现有登录函数,在验证成功后将登录状态存入localStorage,确保页面刷新后状态不丢失:

const ProceedLogin = (e) => {
    e.preventDefault()
    if (validation()) {
        const axiosFunction = async () => {
            try {
                const axiosRes = await axios.get(`http://localhost:3000/user/${username}`)
                const data = axiosRes.data
                
                if (Object.keys(data).length === 0) {
                    toast.error("请输入有效的用户名")
                } else if (data.password === password) {
                    toast.success("登录成功")
                    // 存储登录状态与用户信息到本地存储
                    localStorage.setItem('isLoggedIn', 'true')
                    localStorage.setItem('currentUser', JSON.stringify(data))
                    navigate("/")
                } else {
                    toast.error("密码错误")
                }
            } catch (err) {
                console.log(err);
                toast.error("用户不存在")
            }
        }
        axiosFunction()
    }
}

2. 首页权限控制实现

在首页组件中读取登录状态,根据状态控制操作按钮的显示与功能可用性:

import { useState, useEffect } from 'react';
import axios from 'axios';
import { toast } from 'react-toastify';

const Home = () => {
    const [posts, setPosts] = useState([]);
    const [isLoggedIn, setIsLoggedIn] = useState(false);

    // 页面加载时初始化登录状态并拉取帖子
    useEffect(() => {
        const loggedIn = localStorage.getItem('isLoggedIn') === 'true';
        setIsLoggedIn(loggedIn);
        fetchPosts();
    }, []);

    // 获取帖子列表(游客与登录用户均可访问)
    const fetchPosts = async () => {
        try {
            const res = await axios.get('http://localhost:3000/posts');
            setPosts(res.data);
        } catch (err) {
            toast.error("加载帖子失败");
        }
    };

    // 添加帖子(仅登录用户可执行)
    const handleAddPost = async (newPost) => {
        if (!isLoggedIn) {
            toast.error("请先登录再添加帖子");
            return;
        }
        try {
            await axios.post('http://localhost:3000/posts', newPost);
            fetchPosts();
            toast.success("帖子添加成功");
        } catch (err) {
            toast.error("添加帖子失败");
        }
    };

    // 编辑帖子(仅登录用户可执行)
    const handleEditPost = async (postId, updatedPost) => {
        if (!isLoggedIn) {
            toast.error("请先登录再编辑帖子");
            return;
        }
        try {
            await axios.put(`http://localhost:3000/posts/${postId}`, updatedPost);
            fetchPosts();
            toast.success("帖子编辑成功");
        } catch (err) {
            toast.error("编辑帖子失败");
        }
    };

    // 删除帖子(仅登录用户可执行)
    const handleDeletePost = async (postId) => {
        if (!isLoggedIn) {
            toast.error("请先登录再删除帖子");
            return;
        }
        try {
            await axios.delete(`http://localhost:3000/posts/${postId}`);
            fetchPosts();
            toast.success("帖子删除成功");
        } catch (err) {
            toast.error("删除帖子失败");
        }
    };

    // 登出功能
    const handleLogout = () => {
        localStorage.removeItem('isLoggedIn');
        localStorage.removeItem('currentUser');
        setIsLoggedIn(false);
        toast.success("已登出");
    };

    return (
        <div className="home">
            <h1>帖子列表</h1>
            {/* 登出按钮仅登录后显示 */}
            {isLoggedIn && <button onClick={handleLogout}>登出</button>}
            {/* 添加按钮仅登录后显示 */}
            {isLoggedIn && <button onClick={() => handleAddPost({ title: "新帖子", content: "默认内容" })}>添加帖子</button>}
            
            <div className="posts-list">
                {posts.map(post => (
                    <div key={post.id} className="post-item">
                        <h3>{post.title}</h3>
                        <p>{post.content}</p>
                        {/* 编辑/删除按钮仅登录后显示 */}
                        {isLoggedIn && (
                            <div className="post-actions">
                                <button onClick={() => handleEditPost(post.id, { ...post, title: `编辑:${post.title}` })}>编辑</button>
                                <button onClick={() => handleDeletePost(post.id)}>删除</button>
                            </div>
                        )}
                    </div>
                ))}
            </div>
        </div>
    );
};

export default Home;

3. 补充说明

  • 小型项目用localStorage存储登录状态足够,大型项目建议改用React Context或Redux做全局状态管理
  • 前端权限控制仅做界面层限制,若需要更严格的权限校验,可给JSON Server添加中间件拦截修改类请求(JSON Server本身为轻量工具,适合演示场景)

内容的提问来源于stack exchange,提问作者mohamed Allam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 01:48:37