Meteor/React:重定向组件外部作为 AccountsTemplates.logout() 的回调
Meteor/React: Redirect outside of component as callback of AccountsTemplates.logout()
我正在尝试将 meteor-useraccounts 包与 React 集成到我的 Meteor 应用程序中。我已经走了很远,但我正在努力实现 history.push()
或等效的回调函数 AccountsTemplate.logout()
- 后者是注销用户的内置方式。
回调函数的配置是这样完成的:
AccountsTemplates.configure({
onLogoutHook: myLogoutFunc
})
但我无法在 React.Component 的 "class" 范围内执行此操作。所以我需要定义使用浏览器历史记录的回调函数,但我想它在任何组件范围之外。
对于点击符号In/Out按钮的情况,我找到解决方案如下:
class LogInOutButton extends Component {
constructor(props) {
super(props);
this.state = {
loggedIn: Meteor.userId() ? true : false,
redirect: false
}
this.redirectToSignIn = this.redirectToSignIn.bind(this);
window.logInOutButton = this;
}
redirectToSignIn() {
if (!this.state.loggedIn && document.location.pathname !== "/signIn")
this.setState({redirect: <Redirect to="/signIn" />});
}
render() {
const { redirect } = this.state
return (
<li className="nav-item">
{redirect}
<a className="nav-link" href="#"
onClick={Meteor.userId() ? AccountsTemplates.logout : this.redirectToSignIn}>
{Meteor.userId() ? "Sign Out" : "Sign In"}
</a>
</li>
)
}
}
如您所见,例如,我尝试通过使 window 对象的成员从外部调用 redirectToSignIn()
方法。感觉不对也不行:
var myLogoutFunc = () =>
window.logInOutButton.redirectToSignIn();
我也试过下面的方法:
var myLogoutFunc = withRouter(({history}) =>
<div onLoad={history.push="/signIn"}>
</div>
)
但是,这行不通,因为 withRouter
需要一个组件作为参数,如果我做对了吗?至少这是我试图解释以下错误的方式:
Exception in delivering result of invoking 'logout': TypeError: "props is undefined"
在 withRouter
模块中阅读此内容后:
var withRouter = function withRouter(Component) {
var C = function C(props) {
...
你会如何解决这个问题?
老实说,我放弃了使用包为帐户系统创建UI的想法。
包 meteor-useraccounts 是为 Blaze 制作的,尽管在官方的 Meteor 文档中他们鼓励包装呈现登录表单的 {{> atForm }}
模板,注册等进入 React.Component,我发现它会导致不兼容,尤其是在处理路由时。 (我曾使用包 gadicc:blaze-react-component
进行包装。)
最后我发现自己试图理解这个由多层组成的黑盒子,包括。另一个用于 bootstrap4 预样式。例如我也无法使电子邮件验证工作。
所以我决定放弃一切,开始在 Meteor Accounts and Meteor Passwords API.
之上构建整个 UI 和逻辑。
现在重定向非常简单,因为我可以在自己的 React.Component 中完成。您唯一需要做的就是 import { withRouter } from 'react-router';
,然后 export default withRouter(LogInOutButton);
最后您可以使用 this.props.history.push("/signIn")
重定向:
import React, { Component } from 'react';
import { withRouter } from 'react-router';
class LogInOutButton extends Component {
constructor(props) {
super(props);
this.state = {
loggedIn: Meteor.userId() ? true : false,
}
this.redirectToSignIn = this.redirectToSignIn.bind(this);
}
redirectToSignIn() {
if (this.state.loggedIn)
Meteor.logout()
if (document.location.pathname !== "/signIn")
this.props.history.push("/signIn")
}
render() {
return (
<li className="nav-item">
<a className="nav-link" href="#"
onClick={this.redirectToSignIn}>
{Meteor.userId() ? "Sign Out" : "Sign In"}
</a>
</li>
)
}
}
export default withRouter(LogInOutButton);
PS: (只是我的意见)当然,在构建自己的时候有一些事情需要解决UI/Logic 用于帐户系统。例如表单验证。 (我决定在 HTML5 验证的基础上构建,但使用 bootstrap4 添加我自己的视觉反馈。)
我想在 Meteor 和 React 的情况下,目前根本没有工作包。我都试过了,相信我。它们都让人头疼(当试图将它们与 React 集成时)或不够可定制。如果我从一开始就花时间构建自己的,那么我现在早就完成了。自己动手的好处在于,您知道它是如何工作的,并且以后可以轻松地改进和重用它。
它还有助于保持较低的依赖性,我认为这很重要,因为 Meteor 项目在过去几年中一直在快速发展和变化。当您知道自己做了什么时,可以更轻松地使您的项目保持最新状态。
您是否只是试图在用户注销、已注销或未登录时进入 app/site 时将用户重定向到登录页面?我经常根据 app/routes/permissions/etc.
的复杂性以几种不同的方式进行此操作
我倾向于使用 iron:router 和 Blaze,而不是 React,但我认为最直接的解决方案是易于翻译。我将其放在客户端代码顶层的某处:
Tracker.autorun(function() {
const userDoc = Meteor.user();
const loggingIn = Meteor.loggingIn();
if(!userDoc && !loggingIn) {
Router.go('/'); // Or comparable redirect command
}
});
页面加载时:
如果 userDoc
未定义(意味着用户未成功登录)并且 loggingIn
不为真(意味着 Meteor 未在页面加载时让用户登录),我们将将用户重定向到主页。
注销时:
由于 userDoc
和 loggingIn
都是反应性数据源,因此只要这些变量中的任何一个发生变化,这个 autorun
函数就会重新 运行 。因此,当用户以任何方式注销时,userDoc
将不再定义,条件将解析为 true
并将用户重定向到主页。
登录时:
如果注销的用户登录或开始登录,则不会发生任何事情。该函数将重新 运行,但在 userDoc
或 loggingIn
变量更改时强制自动重定向会变得更加复杂。
我正在尝试将 meteor-useraccounts 包与 React 集成到我的 Meteor 应用程序中。我已经走了很远,但我正在努力实现 history.push()
或等效的回调函数 AccountsTemplate.logout()
- 后者是注销用户的内置方式。
回调函数的配置是这样完成的:
AccountsTemplates.configure({
onLogoutHook: myLogoutFunc
})
但我无法在 React.Component 的 "class" 范围内执行此操作。所以我需要定义使用浏览器历史记录的回调函数,但我想它在任何组件范围之外。
对于点击符号In/Out按钮的情况,我找到解决方案如下:
class LogInOutButton extends Component {
constructor(props) {
super(props);
this.state = {
loggedIn: Meteor.userId() ? true : false,
redirect: false
}
this.redirectToSignIn = this.redirectToSignIn.bind(this);
window.logInOutButton = this;
}
redirectToSignIn() {
if (!this.state.loggedIn && document.location.pathname !== "/signIn")
this.setState({redirect: <Redirect to="/signIn" />});
}
render() {
const { redirect } = this.state
return (
<li className="nav-item">
{redirect}
<a className="nav-link" href="#"
onClick={Meteor.userId() ? AccountsTemplates.logout : this.redirectToSignIn}>
{Meteor.userId() ? "Sign Out" : "Sign In"}
</a>
</li>
)
}
}
如您所见,例如,我尝试通过使 window 对象的成员从外部调用 redirectToSignIn()
方法。感觉不对也不行:
var myLogoutFunc = () =>
window.logInOutButton.redirectToSignIn();
我也试过下面的方法:
var myLogoutFunc = withRouter(({history}) =>
<div onLoad={history.push="/signIn"}>
</div>
)
但是,这行不通,因为 withRouter
需要一个组件作为参数,如果我做对了吗?至少这是我试图解释以下错误的方式:
Exception in delivering result of invoking 'logout': TypeError: "props is undefined"
在 withRouter
模块中阅读此内容后:
var withRouter = function withRouter(Component) {
var C = function C(props) {
...
你会如何解决这个问题?
老实说,我放弃了使用包为帐户系统创建UI的想法。
包 meteor-useraccounts 是为 Blaze 制作的,尽管在官方的 Meteor 文档中他们鼓励包装呈现登录表单的 {{> atForm }}
模板,注册等进入 React.Component,我发现它会导致不兼容,尤其是在处理路由时。 (我曾使用包 gadicc:blaze-react-component
进行包装。)
最后我发现自己试图理解这个由多层组成的黑盒子,包括。另一个用于 bootstrap4 预样式。例如我也无法使电子邮件验证工作。
所以我决定放弃一切,开始在 Meteor Accounts and Meteor Passwords API.
之上构建整个 UI 和逻辑。现在重定向非常简单,因为我可以在自己的 React.Component 中完成。您唯一需要做的就是 import { withRouter } from 'react-router';
,然后 export default withRouter(LogInOutButton);
最后您可以使用 this.props.history.push("/signIn")
重定向:
import React, { Component } from 'react';
import { withRouter } from 'react-router';
class LogInOutButton extends Component {
constructor(props) {
super(props);
this.state = {
loggedIn: Meteor.userId() ? true : false,
}
this.redirectToSignIn = this.redirectToSignIn.bind(this);
}
redirectToSignIn() {
if (this.state.loggedIn)
Meteor.logout()
if (document.location.pathname !== "/signIn")
this.props.history.push("/signIn")
}
render() {
return (
<li className="nav-item">
<a className="nav-link" href="#"
onClick={this.redirectToSignIn}>
{Meteor.userId() ? "Sign Out" : "Sign In"}
</a>
</li>
)
}
}
export default withRouter(LogInOutButton);
PS: (只是我的意见)当然,在构建自己的时候有一些事情需要解决UI/Logic 用于帐户系统。例如表单验证。 (我决定在 HTML5 验证的基础上构建,但使用 bootstrap4 添加我自己的视觉反馈。)
我想在 Meteor 和 React 的情况下,目前根本没有工作包。我都试过了,相信我。它们都让人头疼(当试图将它们与 React 集成时)或不够可定制。如果我从一开始就花时间构建自己的,那么我现在早就完成了。自己动手的好处在于,您知道它是如何工作的,并且以后可以轻松地改进和重用它。
它还有助于保持较低的依赖性,我认为这很重要,因为 Meteor 项目在过去几年中一直在快速发展和变化。当您知道自己做了什么时,可以更轻松地使您的项目保持最新状态。
您是否只是试图在用户注销、已注销或未登录时进入 app/site 时将用户重定向到登录页面?我经常根据 app/routes/permissions/etc.
的复杂性以几种不同的方式进行此操作我倾向于使用 iron:router 和 Blaze,而不是 React,但我认为最直接的解决方案是易于翻译。我将其放在客户端代码顶层的某处:
Tracker.autorun(function() {
const userDoc = Meteor.user();
const loggingIn = Meteor.loggingIn();
if(!userDoc && !loggingIn) {
Router.go('/'); // Or comparable redirect command
}
});
页面加载时:
如果 userDoc
未定义(意味着用户未成功登录)并且 loggingIn
不为真(意味着 Meteor 未在页面加载时让用户登录),我们将将用户重定向到主页。
注销时:
由于 userDoc
和 loggingIn
都是反应性数据源,因此只要这些变量中的任何一个发生变化,这个 autorun
函数就会重新 运行 。因此,当用户以任何方式注销时,userDoc
将不再定义,条件将解析为 true
并将用户重定向到主页。
登录时:
如果注销的用户登录或开始登录,则不会发生任何事情。该函数将重新 运行,但在 userDoc
或 loggingIn
变量更改时强制自动重定向会变得更加复杂。