游牧周记第46期
标签Tags
F1美国站
开发
学易app参加评奖
Expo App Awards 又有一个新的app点子,去expo网站才发现在搞评奖,就报名一下。
creem付款开发小记
没法用stripe,就只能找creem了。 开发挺简单,就是文档太差。
live/test模式的设计不好好搞清楚,还有点容易乱。
首先是虚拟物品购买(非订阅)
跳转结果页面
做充值码ok。
前端主动查询
app用,没法子,只能这样,而且手动。
webhook
可惜不能调用app内部链接。 不然怎么要用前面的前端自主查询。
Jwt的库 jose
GPT推荐。
next/router还是next/navigation
AI回答: 在 Next.js 13+(App Router) 下,正确的是:
import { useRouter } from 'next/navigation'
原因:
-
next/router是 Pages Router(旧版路由)的 hook,只在pages/目录下使用。 -
next/navigation是 App Router 的新 hook,适用于app/目录的'use client'组件。 -
两者 API 有差异:
-
next/navigation的useRouter()只有少量方法:push(),replace(),refresh(),back()。 -
next/router提供更多事件和状态,但不适合 App Router。
-
✅ 结论:
- 你的项目是基于 App Router(app 目录),应该使用:
import { useRouter } from 'next/navigation'
- 如果你在 pages 目录下开发旧式页面,才用
next/router。
localStorage和cookie的选择
目前涉及多个网站共用user登录中心的问题,差不多就是SSO。 AI分析大概这样:
| 策略 | 存储位置 | 子域可否访问 | 安全性 | 推荐程度 |
|---|---|---|---|---|
| localStorage 保存 JWT | ❌ 不共享 | ❌ | ⚠️ 可被 JS 访问,容易被 XSS 攻击 | 不推荐跨域用 |
cookie(HttpOnly + Secure) | ✅ 可通过设置 Domain=.suheapp.org 共享 | ✅ | ✅ 高 | ✅ 推荐 |
URL 参数传递 JWT(?token=xxx) | 临时共享 | ✅ | ⚠️ 容易被泄露 | ⚠️ 仅限回调临时用途 |
| 所以cookie是最好的? |
nextjs的奇葩问题
代码如下:
'use client'
import { useEffect, useState } from 'react'
import { PUBLIC_ENV } from '@/lib/env/env.client'
export default function HomePage() {
const [user, setUser] = useState<{ sub: string; email?: string } | null>(null)
console.log('app user ---', user)
const [loading, setLoading] = useState(true)
useEffect(() => {
const fetchUser = async () => {
try {
const res = await fetch('/api/verify-jwt')
console.log('res ---', res)
const data = await res.json()
if (res.ok && data) setUser(data)
} catch (err) {
console.error(err)
} finally {
setLoading(false)
}
}
fetchUser()
}, [])
if (loading) return <div className="p-4 text-center">Loading...</div>
return (
<div className="p-4 text-center">
{user ? (
<>
<h1 className="text-2xl font-bold mb-4">Welcome, {user.email || user.sub}</h1>
<a
href={`${PUBLIC_ENV.USER_WEB_URL}/sign-out?redirect_url=${encodeURIComponent(window.location.origin)}`}
className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
>
Sign Out
</a>
</>
) : (
<a
href={`${PUBLIC_ENV.USER_WEB_URL}/sign-in?redirect_url=${encodeURIComponent(window.location.origin)}`}
className="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
>
Sign In
</a>
)}
</div>
)
}
很简单的一个useEffect渲染。 然而console.log('res ---', res)永远不执行,console.log('app user ---', user)永远是null,但实际UI上已经显示获得的user信息,为啥?
ChatGPT发现了它的强项,解释得很精彩,但也很令人困惑:
非常棒的观察 👍
这其实是一个 React + Next.js hydration(同构渲染) 的“错觉问题”,不是你的逻辑错。
下面我来帮你完整解释发生了什么 👇
🧠 现象总结
-
页面 UI ✅ 能正确显示出用户信息(说明
setUser()确实生效了)。 -
但你在控制台看到:
-
❌
console.log('res ---', res)没出现; -
❌
console.log('app user ---', user)永远是null; -
✅ 但渲染结果里 user 有值!
-
听起来很矛盾,对吧?其实完全合理。
🧩 真相:Hydration(服务端渲染 + 客户端挂载)
在 Next.js 的 "use client" 页面中:
-
初始渲染:
-
Next.js 先在服务器(Node.js)端执行一遍组件(SSR),生成静态 HTML。
-
这时 React 并没有运行
useEffect(),因为它只在浏览器端运行。
所以:console.log('app user ---', user)在 SSR 阶段输出一次(
user还是null)。
-
-
客户端挂载阶段(Hydration):
-
浏览器端 React 接管 HTML(Hydration),
-
再执行
useEffect(), -
这时发出 fetch 请求并调用
setUser(data)。
-
-
问题是:
