我有四个React组件:
App
或类似的)Header
App
孩子
Profile
页LogoutLink
,由Profile
我正在使用Auth0实施用户身份验证/登录系统。当用户登录时(通过Header
中的“登录”按钮),App
会更改Context
对象的User
以包含从Auth0检索到的所有数据。然后,系统的任何需要它的用户数据都可以访问。
登录后,UI会自动更新(使用Context
更改),以便Header
现在显示“Hey there {name}”而不是“Login”。这也是指向Profile
页面/组件的链接(使用React Router的<Link to="/profile></Link>
元素)。
在Profile
页面上有一个LogoutLink
。单击时,会将用户注销,然后返回主页。它还应自动更新UI以将Header
中的消息从“Hey there {name}”更改为“Login”。这是通过再次Context
更改完成的。但是,此功能实际上并不起作用 - 用户已成功注销,但要查看上面描述的更改,用户需要刷新整个页面。 this.context.user
未更新并发送回Profile
和Header
。我知道这是因为Redux和它的单向数据流(即数据可以只有向下,而不是向上),但我需要找到解决方法。
以下是我的基本代码:
LogoutLink.js
export default class LogoutLink extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.state = {
user: null,
};
}
static propTypes = {
value: React.PropTypes.string,
}
static contextTypes = {
user: React.PropTypes.object,
} // get context so this.context is available to get initial user data (before logout)
static childContextTypes = {
user: React.PropTypes.object,
}
getChildContext() {
return {user: this.state.user}
} // these two are for updating context
componentWillMount() {
this.setState({ user: this.context.user });
} // set the internal LogoutLink state
onClick() {
this.setState({ user: null }); // set the internal user state to null following logout
}
renderLogoutLink() {
const {value} = this.props;
const {user} = this.state;
if (user != null) {
return <Link to="/profile" onClick={this.onClick}>{value}</Link>
} else {
return <span>You're already logged out!</span>
}
}
render() {
return <span>{this.renderLogoutLink()}</span>
}
}
Header.js
:
export default class Header extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.showLock = this.showLock.bind(this); // lock is the Auth0 module responsible for Login, also passed down by context
}
static contextTypes = {
user: React.PropTypes.object,
lock: React.PropTypes.object,
}
showLock() {
const {lock} = this.context;
lock.show();
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
if (this.context.user == null && nextContext.user != null) {
return true;
} else if (this.context.user != null && nextContext.user == null) {
return true;
}
return false;
} // after the LogoutLink is clicked, this still returns false
renderLoginButton() {
const {user} = this.context;
if (user) {
const name = user.nickname;
return <Link to="/profile">Hey there {name}!</Link>
} else {
return <button onClick={this.showLock}>Login</button>
}
}
render() {
return (
<header>
{this.renderLoginButton()}
</header>
);
}
}
我正在关注有关Context的官方React文档并对其进行更新,请点击此处:https://facebook.github.io/react/docs/context.html
正如我所说,我知道为什么这不起作用:数据只能以一种方式发送。但我需要找到一种方法来使这项工作,说实话,我认为我已经盯着这个太久了,现在已经没有选择,我的大脑有点疲惫。
答案 0 :(得分:1)
找到解决此问题的方法。在我设置User项初始上下文的App.js
代码中,我在User上添加了一个方法,将User设置为null,然后通过应用程序向下渗透。在Logout链接中,它调用此方法。这是代码:
在App.js
:
profile.logout = () => {
this.setState({ profile: null });
}
getChildContext()
方法然后根据此状态更改设置用户上下文:
getChildContext() {
return {
user: this.state.profile
};
}
在LogoutLink.js
:
onClick() {
const {user} = this.context;
user.logout();
}
答案 1 :(得分:0)
React&#34; context&#34;功能很有用,但也很复杂和古怪,这就是为什么在使用它时仍有许多注意事项。特别是,我相信从false
返回shouldComponentUpdate
的组件会导致较低的组件在上下文内容发生更改时不会更新。
我的建议是尽可能少地使用上下文,并且只针对不更改的数据。将更改的数据(例如当前用户)放入Redux xtate。