Kar*_*mar 9 reactjs react-router server-side-rendering react-redux next.js
目标:如果登录用户尝试手动转到 /auth/signin,我想将其重定向到主页。
登录页面/组件:
const Signin = ({ currentUser }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { doRequest, errors } = useRequest({
url: '/api/users/signin',
method: 'post',
body: {
email, password
},
onSuccess: () => Router.push('/')
});
useEffect(() => {
const loggedUser = () => {
if (currentUser) {
Router.push('/');
}
};
loggedUser();
}, []);
Run Code Online (Sandbox Code Playgroud)
自定义 _app 组件:
const AppComponent = ({ Component, pageProps, currentUser }) => {
return (
<div>
<Header currentUser={currentUser} />
<Component {...pageProps} currentUser={currentUser} />
</div>
)
};
AppComponent.getInitialProps = async (appContext) => {
const client = buildClient(appContext.ctx);
const { data } = await client.get('/api/users/currentuser');
let pageProps = {};
if (appContext.Component.getInitialProps) {
pageProps = await appContext.Component.getInitialProps(appContext.ctx);
}
return {
pageProps,
...data
}
};
export default AppComponent;
Run Code Online (Sandbox Code Playgroud)
问题:
我试过这个,但这会导致轻微的延迟,因为它不会在服务器端呈现。延迟我的意思是:它显示了我在重定向前一秒左右不想显示的页面。
我可以使用加载标志或一堆 if else 条件,但这将是一种解决方法,最好的方法/实践是什么,处理此问题是什么?
我想出的另一个解决方案:
import Router from 'next/router';
export default (ctx, target) => {
if (ctx.res) {
// server
ctx.res.writeHead(303, { Location: target });
ctx.res.end();
} else {
// client
Router.push(target);
}
}
Run Code Online (Sandbox Code Playgroud)
import React from 'react';
import redirect from './redirect';
const withAuth = (Component) => {
return class AuthComponent extends React.Component {
static async getInitialProps(ctx, { currentUser }) {
if (!currentUser) {
return redirect(ctx, "/");
}
}
render() {
return <Component {...this.props} />
}
}
}
export default withAuth;
Run Code Online (Sandbox Code Playgroud)
export default withAuth(NewTicket);
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来处理这个问题?非常感谢您的帮助。
ala*_*ita 13
我真的建议您查看示例以了解 NextJS 建议如何处理此问题。资源真的很好!
https://github.com/vercel/next.js/tree/master/examples
例如,您可以使用next-auth
which 是一个开源身份验证选项。
例子在这里。https://github.com/vercel/next.js/tree/master/examples/with-next-auth
// _app.js
import { Provider } from 'next-auth/client'
import '../styles.css'
const App = ({ Component, pageProps }) => {
const { session } = pageProps
return (
<Provider options={{ site: process.env.SITE }} session={session}>
<Component {...pageProps} />
</Provider>
)
}
export default App
Run Code Online (Sandbox Code Playgroud)
// _app.js
import { Provider } from 'next-auth/client'
import '../styles.css'
const App = ({ Component, pageProps }) => {
const { session } = pageProps
return (
<Provider options={{ site: process.env.SITE }} session={session}>
<Component {...pageProps} />
</Provider>
)
}
export default App
Run Code Online (Sandbox Code Playgroud)
所以上面的选项是 defo 一个服务器端呈现的应用程序,因为我们使用 /api 路径进行身份验证。如果您想要一个无服务器解决方案,您可能必须将 /api 路径中的所有内容拉入 lambda (AWS Lambda) + 网关 api (AWS Api Gateway)。您只需要一个连接到该 api 的自定义钩子。当然,你也可以用不同的方式来做到这一点。
这是另一个使用 firebase 的身份验证示例。
https://github.com/vercel/next.js/tree/master/examples/with-firebase-authentication
另一个使用 Passport.js 的例子
https://github.com/vercel/next.js/tree/master/examples/with-passport
您还询问了加载行为,这个示例可能对您有所帮助
https://github.com/vercel/next.js/tree/master/examples/with-loading
自定义 _app 组件通常是顶级包装器(不是最顶级的 _document 适合该描述)。
实际上,我会在 _app 下一级创建一个登录组件。通常我会在 Layout 组件中实现这种模式,或者像上面的例子那样,使用 api 路径或实用程序函数。
下面是一个使用自定义“钩子”和 getServerSideProps 的示例。
我正在使用react-query,但您可以使用任何数据获取工具。
// /pages/login.jsx
import SessionForm from '../components/SessionForm'
import { useSessionCondition } from '../hooks/useSessionCondition'
export const getServerSideProps = useSessionCondition(false, '/app')
const Login = () => {
return (
<SessionForm isLogin/>
)
}
export default Login
Run Code Online (Sandbox Code Playgroud)
// /pages/login.jsx
import SessionForm from '../components/SessionForm'
import { useSessionCondition } from '../hooks/useSessionCondition'
export const getServerSideProps = useSessionCondition(false, '/app')
const Login = () => {
return (
<SessionForm isLogin/>
)
}
export default Login
Run Code Online (Sandbox Code Playgroud)
Ale*_*ks 3
将 NextJs 升级到 9.3+ 并getServerSideProps
使用getInitialProps
. getServerSideProps
与getInitialProps
. 如果身份验证失败则重定向getServerSideProps
。
归档时间: |
|
查看次数: |
22076 次 |
最近记录: |