如何在Rails+React项目中结合ERB实现React组件内用户登录状态判断
解决方案
你可以通过两种成熟的方案实现React组件内的登录状态校验,两种方案都可以适配你当前的技术栈:
方案1:复用现有GraphQL查询逻辑(推荐)
你当前的QUERY语句已经包含了viewer字段的查询,绝大多数Rails+GraphQL的鉴权逻辑会默认返回:
- 已登录状态:
viewer为当前用户对象,包含id等字段 - 未登录状态:
viewer为null
实现步骤:
- 组件内先通过
viewer字段判断登录状态 - 点赞按钮点击时优先校验登录状态,未登录直接跳转到登录页
- 补充说明:你当前的
upVote仅修改了本地数据,未同步到后端,实际使用时需要补全GraphQL突变调用逻辑
修改后的完整组件代码:
import * as React from 'react'; import gql from 'graphql-tag'; import { useQuery } from 'react-apollo'; import renderComponent from './utils/renderComponent'; const QUERY = gql` query PostsPage { viewer { id } ReviewsAll { id title tagline url commentsCount votes } } `; // 你后续可以替换为真实的GraphQL突变调用 function upVote(review) { review.votes += 1; } function ReviewsIndex() { const { data, loading, error } = useQuery(QUERY); if (loading) return 'Loading...'; if (error) return `Error! ${error.message}`; // 新增:通过viewer判断登录状态 const isLoggedIn = !!data?.viewer?.id; // 登录页路径和你erb里的Login链接对应即可 const loginPath = '/users/sign_in'; return ( <div className="container"> {data.reviewsAll.map((review) => ( <article className="review" key={review.id}> <h2> <a href={`/reviews/${review.id}`}>{review.title}</a> </h2> <div className="myUrl"> <a href={review.url}>{review.url}</a> </div> <div className="tagline">{review.tagline}</div> <footer> <button onClick={() => { if (!isLoggedIn) { // 未登录跳转到登录页 window.location.href = loginPath; return; } // 已登录执行点赞逻辑 upVote(review); }} > 🔼 {review.votes} </button> </footer> </article> ))} </div> ); } renderComponent(ReviewsIndex);
方案2:ERB模板注入全局登录状态(更简单)
如果你不想依赖GraphQL返回登录状态,可以直接在Rails的布局模板里把登录状态注入到全局window对象,React组件直接读取即可:
第一步:修改application.html.erb
在head标签内新增如下脚本:
<head> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/> <title>Kittynews</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all' %> <%= javascript_include_tag 'application' %> <!-- 新增:注入全局登录状态 --> <script> window.userSignedIn = <%= user_signed_in? ? 'true' : 'false' %>; window.currentUserId = <%= user_signed_in? ? current_user.id.to_json : 'null' %>; </script> </head>
第二步:React组件内直接读取全局状态
把方案1里的isLoggedIn判断替换为:
const isLoggedIn = window.userSignedIn;
后续逻辑和方案1完全一致即可。
内容的提问来源于stack exchange,提问作者NBash
相关产品推荐
相关产品推荐

