我有一个用户登录的用例。一旦用户登录,就应该显示另一个组件。这对我不起作用。我必须再次点击登录按钮以显示另一个组件或必须刷新页面。
这就是我所做的
这是父组件
const mapStateToProps = state => {
return {
user: state.loginReducer
}
}
class App extends React.Component {
state = {
hasToken: false
}
componentDidMount() {
const { user } = this.props;
window.chrome.storage.sync.get(['user_token'], result => {
if ((user && user.access_token) || result.user_token) {
console.log('user_token in cdm', result, user);
this.setState({ hasToken: true })
}
})
}
componentWillReceiveProps(nextProps) {
if (this.props.user !== nextProps.user) {
window.chrome.storage.sync.get(['user_token'], result => {
if (nextProps.user.length || result.user_token) {
this.setState({ hasToken: true })
}
})
}
}
anotherComponent() { // just to show the demo
return (
<div class="content">
component to show when the user logs in
</div>
)
}
render() {
const { hasToken } = this.state;
return (
<div>
<Header />
{ !hasToken ? <Login /> : this.anotherComponent()}
</div>
)
}
}
export default connect(mapStateToProps, null)(App);
login.js
const mapDispatchToProps = dispatch => ({
userLogin: user => dispatch(login(user))
})
class Login extends React.Component {
state = {
user: {
email:"",
password: "",
grant_type: "password"
}
}
handleChange = e => {
this.setState({user: {...this.state.user, [e.target.name]: e.target.value}})
}
handleSubmit = e => {
e.preventDefault();
this.props.userLogin(this.state.user);
}
render() {
const { user } = this.state;
return (
<Grid>
<Row className="pad-10">
<Col sm={12} md={6} mdOffset={3}>
<Form onSubmit={this.handleSubmit}>
<FormGroup controlId="email">
<ControlLabel>Email</ControlLabel>
<FormControl
type="email"
placeholder="Email"
name="email"
onChange={this.handleChange}
value={user.email}
/>
</FormGroup>
<FormGroup controlId="password">
<ControlLabel>Password</ControlLabel>
<FormControl
type="password"
placeholder="Password"
name="password"
onChange={this.handleChange}
value={user.password}
/>
</FormGroup>
<FormGroup>
<Button type="submit">Sign in</Button>
</FormGroup>
</Form>
</Col>
</Row>
</Grid>
);
}
}
export default connect(null, mapDispatchToProps)(Login);
我没有使用任何路由器概念所以我想要做的是当用户点击登录按钮时,如果登录成功,则令牌从服务器响应并且被检查以便如果成功,则用户将显示另一个组件。
更新
export const login = action(LOGIN, 'user');
export const loginSuccess = action(LOGIN_SUCCESS, 'data');
export const loginFailure = action(LOGIN_FAILURE, 'error');
reducer code
const initialState = {
fetching: false,
error: null,
user: []
}
function loginReducer(state=initialState, action) {
switch (action.type) {
case LOGIN:
return {...state, fetching: true}
case LOGIN_SUCCESS:
return {...state, fetching: false, user: action.data.access_token}
case LOGIN_FAILURE:
return {...state, fetching: false, error: action.error}
default:
return state;
}
}
export default loginReducer;
答案 0 :(得分:0)
我不确切知道window.chrome.storage.sync
是如何工作的,但显而易见的解决方案(乍一看)是:
// parent component
render() {
const { user } = this.props;
return (
<div>
<Header />
{ !user ? <Login /> : this.anotherComponent()}
</div>
)
}
您必须从您的州获得用户 当您带上减速器/动作时,我会提供更多详细信息
答案 1 :(得分:0)
您的代码无效的问题是因为App
组件只会呈现一次,无论用户是否登录过天气。因此,稍后当用户登录时,您的应用程序组件不会重新呈现。
可以有很多方法来解决这个问题。我建议你做的是这样的:
将onUserLogin
回调传递给类似
<LoginModal isModalOpen={isModalOpen} onLoginClick={this.onLoginClick} />
然后在setState
函数中执行onLoginClick
以确保使用更改的道具呈现组件。
onLoginClick = () => {
if (!this.state.isUserLoggedIn) {
this.setState({
isModalOpen:!this.state.isModalOpen,
});
}
}