我试图学习反应,但当我设置已验证的道具时,我被困在获取头组件的重新渲染。我一直在阅读它,但有很多不同的编码风格,我似乎无法有效地实现它们中的任何一种。我试图让它在this.props.authenticated更改时重新呈现。这是我最近的尝试,我无法让它在代码的小部分工作,所以我认为我会做整个块。当我更新商店时,我的一个控制器没有渲染
import React, { Component, PropTypes } from 'react';
import logo from '../logo.svg';
import { Link } from 'react-router-dom';
import {connect} from 'react-redux';
import * as Actions from '../actions/auth';
class Header extends Component {
constructor() {
super();
this.state = { authenticated: false };
}
handleSignout() {
this.props.signOutUser();
}
logOut(event) {
event.preventDefault();
this.props.actions.logOutUser();
}
render() {
if (this.props.authenticated){
return (
<div>
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Student Assist App</h2>
</div>
</div>
<div className="navMenu">
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/PhoneNumbers">PhoneNumbers</Link></li>
<li><Link to="/Addresses" > Addresses</Link></li>
<li><Link to="/Credits" > Credits</Link></li>
</ul>
</div>
<div className="authMenu">
<ul className="list-inline">
{/*<li><img src={profile.picture} height="40px" /></li>
<li><span>Welcome, {profile.nickname}</span></li>*/}
<Link to="/Home" > logout</Link>
</ul>
</div>
</div>
);
}else{
return (
<div>
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Student Assist App</h2>
</div>
</div>
<div className="navMenu">
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/PhoneNumbers">PhoneNumbers</Link></li>
<li><Link to="/Addresses" > Addresses</Link></li>
<li><Link to="/Credits" > Credits</Link></li>
</ul>
</div>
<div className="authMenu">
<ul className="list-inline">
<li><Link to="/SignUp" > Sign Up</Link></li>
<li><Link to="/Login" > Login</Link></li>
</ul>
</div>
</div>
);
}
}
}
Header.propTypes = {
actions: PropTypes.object.isRequired
}
function mapStateToProps(state, ownProps) {
return {
authenticated: state.authenticated
}
}
export default connect(mapStateToProps, Actions)(Header);
标题位于应用程序容器中。
import React, { Component, PropTypes } from 'react';
import { ConnectedRouter } from 'react-router-redux';
import { connect } from 'react-redux'
import { history } from '../store/configureStore';
import { Route, Redirect } from 'react-router-dom';
import Header from '../components/header'
import Home from '../components/home'
import Addresses from '../containers/addresses'
import PhoneNumbers from '../containers/phoneNumbers'
import NotAuthroised from '../components/notAuthorised'
import Credits from '../components/credits'
import LogInPage from '../components/logInPage'
import LogIn from '../components/logInPage'
import SignUp from '../containers/signup'
import '../css/App.css';
const PrivateRoute = ({component: Component, authenticated, ...props}) => {
return (
<Route
{...props}
render={(props) => authenticated === true
? <Component {...props} />
: <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
/>
);
};
class App extends Component {
constructor(props) {
super(props)
this.handleLoginClick = this.handleLoginClick.bind(this)
this.handleLogoutClick = this.handleLogoutClick.bind(this)
}
handleLoginClick() {
this.props.login()
}
handleLogoutClick() {
this.props.logout()
}
render() {
const { authenticated, profile } = this.props
return (
<ConnectedRouter history={history}>
<div>
<Header
authenticated={authenticated}
profile={profile}
onLoginClick={this.handleLoginClick}
onLogoutClick={this.handleLogoutClick}
/>
<Route exact={true} path="/" component={Home}/>
<Route path="/Home" component={Home}/>
<Route path="/PhoneNumbers" component={PhoneNumbers}/>
<PrivateRoute authenticated={this.props.authenticated } path="/Addresses" component={Addresses}/>
<Route path="/NotAuthroised" component={NotAuthroised}/>
<Route path="/Credits" component={Credits}/>
<Route path="/Login" component={LogIn}/>
<Route path="/SignUp" component={SignUp}/>
</div>
</ConnectedRouter>
);
}
}
const mapStateToProps = (state) => {
return { authenticated: state.auth.authenticated };
};
export default connect(mapStateToProps)(App);
该应用程序容器被index.js
import './index.css';
import { Provider } from 'react-redux';
import { configureStore } from './store/configureStore'
import App from './containers/App';
import React from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
const store = configureStore()
//store.dispatch(loadAddresses());
ReactDOM.render(<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'));
registerServiceWorker();
登录组件正在改变的认证的值称为是
import React, {PropTypes} from 'react';
import TextInput from './common/textInput';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as sessionActions from '../actions/auth';
class LogInPage extends React.Component {
constructor(props) {
super(props);
this.state = {credentials: {email: '', password: ''}}
this.onChange = this.onChange.bind(this);
this.onSave = this.onSave.bind(this);
}
onChange(event) {
const field = event.target.name;
const credentials = this.state.credentials;
credentials[field] = event.target.value;
return this.setState({credentials: credentials});
}
onSave(event) {
event.preventDefault();
this.props.actions.signInUser(this.state.credentials);
}
render() {
return (
< div>
< form>
< TextInput
name="username"
label="Username"
value={this.state.credentials.username}
onChange={this.onChange}/>
< TextInput
name="password"
label="password"
type="password"
value={this.state.credentials.password}
onChange={this.onChange}/>
< input
type="submit"
className="btn btn-primary"
onClick={this.onSave}/>
</form>
</div>
);
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(sessionActions, dispatch)
};
}
export default connect(null, mapDispatchToProps)(LogInPage);
的signInUser方法是在动作/ AUTH。 js
import * as types from './actionTypes';
import decode from 'jwt-decode';
import sessionApi from '../api/authApi';
const ID_TOKEN_KEY = 'jwt'
export function signOutUser() {
sessionStorage.removeItem(ID_TOKEN_KEY);
return {
type: types.SIGN_OUT_USER
}
}
export function signInUser(credentials) {
console.log('singing user is with credentials ' + credentials);
return function(dispatch) {
return sessionApi.login(credentials).then(response => {
sessionStorage.setItem(ID_TOKEN_KEY, response.access_token);
dispatch(authUser());
}).catch(error => {
console.log('we caught an error ' + error)
dispatch(authError(error));
});
};
}
export function isLoggedIn() {
return function(dispatch) {
const idToken = getIdToken()
if (!!idToken && !isTokenExpired(idToken)){
dispatch(authUser());
}else{
console.log('is logged in issue ')
dispatch(authError('Not logged in'));
}
}
}
export function getIdToken() {
console.log('the token is now ' + sessionStorage.getItem(ID_TOKEN_KEY));
return sessionStorage.getItem(ID_TOKEN_KEY);
}
function getTokenExpirationDate(encodedToken) {
console.log('in get Exp date with encoded token ' + encodedToken);
const token = decode(encodedToken);
if (!token.exp) { return null; }
const date = new Date(0);
date.setUTCSeconds(token.exp);
return date;
}
function isTokenExpired(token) {
console.log('were in isTokenExpired');
const expirationDate = getTokenExpirationDate(token);
return expirationDate < new Date();
}
export function authUser() {
return {
type: types.AUTH_USER
}
}
export function authError(error) {
return {
type: types.AUTH_ERROR,
payload: error
}
}
认证减速是
import * as types from '../actions/actionTypes';
import initialState from './initialState';
//import history from '../history'
export default function auth(state = initialState, action) {
switch (action.type) {
case types.AUTH_USER:
console.log('we have an auth user request')
return {
authenticated: true,
error : null
};
case types.SIGN_OUT_USER:
console.log('we have an sign out request')
return {
authenticated: false,
error : null
};
case types.AUTH_ERROR:
console.log('we have an auth error request')
return {
error: action.payload.message
};
default:
return state;
}
}
,合并的减速是rootReducer
import * as ActionTypes from '../actions/auth'
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import { reducer } from 'redux-form';
import phoneNumbers from './phoneNumbers';
import addresses from './addresses';
import auth from './auth';
const rootReducer = combineReducers({
auth,
addresses,
phoneNumbers,
routerReducer,
reducer
});
export default rootReducer;
配置商店看起来像
import { isLoggedIn } from '../actions/auth';
import {createStore, compose, applyMiddleware} from 'redux';
import { routerMiddleware } from 'react-router-redux';
import rootReducer from '../reducers/rootReducer';
import thunk from 'redux-thunk';
import createHistory from 'history/createBrowserHistory';
import ReduxPromise from 'redux-promise'
export const history = createHistory();
export function configureStore(initialState) {
const store = createStore(
rootReducer,
initialState,
compose (
applyMiddleware(thunk, ReduxPromise, routerMiddleware(history)),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
);
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers/rootReducer',() => {
const nextRootReducer = require('../reducers/rootReducer').default;
store.replaceReducer(nextRootReducer);
});
}
store.dispatch(isLoggedIn());
return store;
}
和initialState.js看起来是这样的。
import { isLoggedIn } from '../actions/auth';
import {createStore, compose, applyMiddleware} from 'redux';
import { routerMiddleware } from 'react-router-redux';
import rootReducer from '../reducers/rootReducer';
import thunk from 'redux-thunk';
import createHistory from 'history/createBrowserHistory';
import ReduxPromise from 'redux-promise'
export const history = createHistory();
export function configureStore(initialState) {
const store = createStore(
rootReducer,
initialState,
compose (
applyMiddleware(thunk, ReduxPromise, routerMiddleware(history)),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
);
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers/rootReducer',() => {
const nextRootReducer = require('../reducers/rootReducer').default;
store.replaceReducer(nextRootReducer);
});
}
store.dispatch(isLoggedIn());
return store;
}
对不起所有的代码,但我觉得我经历过这些文件的代码之后,我有不知道为什么它不工作,因为我可以从API获取数据,既当认证是必需的,什么时候不需要。 我假设我犯了一个愚蠢的初学者错误,但如果有人能让我知道那个错误是什么,那将会非常棒。
这是我创建应用程序和我在安装时安装的其他模块的过程。
run create-react-app
run insatll react-router-dom --save
run intstall auth0-lock --save
run install redux --save
run install redux-thunk --save
npm install redux-logger --save
npm install react-redux --save
npm install [email protected] --save //this needs to be v5 to be compatible with react-router-dom v4
npm install jwt-decode --save
npm install redux-promise --save
npm install history --save
npm install --save redux-form
谢谢您的帮助..
问题是什么? 道具不变?道具改变了,但组件不重新渲染?组件根本没有渲染? – Andrew
嘿安德鲁,问题是,我完成登录后,(this.props.authenticated)道具被更改,但标题不会重新呈现。完成登录后,标题应显示“登出”链接,但始终显示登录链接。 –