目标:如果已登录用户尝试手动访问/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();
}, []);
自定义 _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;
问题:
我尝试过这个方法,但这会导致轻微的延迟,因为它不会在服务器端渲染。 所谓的延迟是指:在重定向之前,它会显示我不想要显示的页面大约一秒钟左右。
我可以使用加载符号或一堆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);
}
}
- 然后我创建了两个HOC(用于已登录和未登录用户)用于保护路由:
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;
- 然后我用它来包裹组件,以保护页面:
export default withAuth(NewTicket);
有没有更好的方法来处理这个问题?非常感谢帮助。