我正在尝试使用React / Redux / Node.js实现Twitter身份验证。后端部分工作正常,因为前端获取了正确的数据。
我现在面临的问题是前端。更具体地,当在成功认证之后接收到令牌时,调度动作,从而结果props
被更新。但是,这不会发生。这是代码:
Header.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import TwitterLogin from 'react-twitter-auth';
import { connect } from 'react-redux';
import { loginSuccess, logout } from './redux/actions/actions';
import 'bulma/css/bulma.css';
class Header extends Component {
constructor(props) {
super(props);
this.onSuccess = this.onSuccess.bind(this);
this.onFailed = this.onFailed.bind(this);
}
onSuccess = (response) => {
const token = response.headers.get('x-auth-token');
response.json().then(user => {
if (token) {
this.props.loginSuccess(user, token);
}
});
};
onFailed = (error) => {
alert(error);
};
logout = () => {
this.props.logout();
};
render() {
let content = this.props.isAuthenticated === true ?
(
<div>
<div>
<Link className="button is-primary" to="/profile">Profile</Link>
<button onClick={this.logout} className="button" >
Log out
</button>
</div>
</div>
) :
(
<TwitterLogin
loginUrl="http://localhost:5000/api/auth/twitter"
onFailure={this.onFailed} onSuccess={this.onSuccess}
requestTokenUrl="http://localhost:5000/api/auth/twitter/reverse"
className="button" />
);
return (
<header className="navbar has-shadow is-spaced">
<div className="container">
<div className="navbar-brand">
<h1 className="title is-4">
<Link to="/" className="navbar-item">
<strong>App</strong>
</Link>
</h1>
</div>
<div className="navbar-end">
<div className="buttons">
{content}
</div>
</div>
</div>
</header>
);
}
}
const mapStateToProps = ({token, user, isAuthenticated}) => ({token, user, isAuthenticated});
export default connect(
mapStateToProps,
{loginSuccess,
logout})(Header);
actions.js
export const loginSuccess = (user, token) => {
return (dispatch) => {
dispatch({type: 'LOGIN_SUCCESS', payload: {user, token}})
}
}
reducers.js
const initialState = {
token: null,
user: null,
isAuthenticated: false,
error: false
};
export default (state=initialState, action) => {
switch (action.type) {
case 'LOGOUT':
localStorage.removeItem('user');
return initialState;
case 'LOGIN_ERROR':
return {
...state,
error: true
}
case 'LOGIN_SUCCESS':
return {
token: action.payload.token,
user: action.payload.user,
isAuthenticated: true,
error: false
}
default:
return state;
}
}
store.js
import {applyMiddleware, createStore} from 'redux';
import thunkMiddleware from 'redux-thunk';
import reducer from './reducer';
const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);
export const store = createStoreWithMiddleware(reducer);
我在这里想念什么? onSuccess 函数中缺少什么吗?
谢谢!
答案 0 :(得分:0)
请尝试替换
case 'LOGIN_SUCCESS':
return {
token: action.payload.token,
user: action.payload.user,
isAuthenticated: true,
error: false
}
作者:
case 'LOGIN_SUCCESS':
return {
...state,token: action.payload.token,
user: action.payload.user,
isAuthenticated: true,
error: false
}
答案 1 :(得分:0)
我发现了问题!我以错误的方式声明了mapStateToProps
。
正确的代码如下:
Header.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import TwitterLogin from 'react-twitter-auth';
import { connect } from 'react-redux';
import { loginSuccess, logout } from './redux/actions/actions';
import 'bulma/css/bulma.css';
class Header extends Component {
constructor(props) {
super(props);
this.onSuccess = this.onSuccess.bind(this);
this.onFailed = this.onFailed.bind(this);
}
onSuccess = (response) => {
const token = response.headers.get('x-auth-token');
response.json().then(user => {
if (token) {
this.props.loginSuccess(user, token);
}
});
};
onFailed = (error) => {
alert(error);
};
logout = () => {
this.props.logout();
};
render() {
let content = this.props.users.isAuthenticated === true ?
(
<div>
<div>
<Link className="button is-primary" to="/profile">Profile</Link>
<button onClick={this.logout} className="button" >
Log out
</button>
</div>
</div>
) :
(
<TwitterLogin
loginUrl="http://localhost:5000/api/auth/twitter"
onFailure={this.onFailed} onSuccess={this.onSuccess}
requestTokenUrl="http://localhost:5000/api/auth/twitter/reverse"
className="button" />
);
return (
<header className="navbar has-shadow is-spaced">
<div className="container">
<div className="navbar-brand">
<h1 className="title is-4">
<Link to="/" className="navbar-item">
<strong>App</strong>
</Link>
</h1>
</div>
<div className="navbar-end">
<div className="buttons">
{content}
</div>
</div>
</div>
</header>
);
}
}
const mapStateToProps = ({users}) => ({users});
export default connect(
mapStateToProps,
{loginSuccess,
logout})(Header);
以下是我结合减速器的代码:
reducer.js
import { combineReducers } from 'redux';
import users from './reducers/users';
import polls from './reducers/polls';
export default combineReducers({
users,
polls
});
通过使用此代码,我可以看到在调度动作之后更新了道具。
感谢您的帮助!