【发布时间】:2019-02-20 22:03:24
【问题描述】:
我刚开始学习 Redux,我遇到了这个错误,似乎无法弄清楚我哪里出错了。在我的 profileReducer.js 文件中,我设置了一个 initialState 以使 profile 等于 null。在某个地方,有些事情失败了,如果我 console.log(this.state) 配置文件未定义。
错误:
TypeError: Cannot read property 'profile' of undefined
Dashboard.render
src/components/dashboard/Dashboard.js:11
8 | this.props.getCurrentProfile();
9 | }
10 |
> 11 | render() {
12 | const { user } = this.props.auth;
13 | const { profile, loading } = this.props.profile;
14 |
profileReducer.js
import {
GET_PROFILE,
PROFILE_LOADING,
CLEAR_CURRENT_PROFILE
} from "../actions/types";
const initialState = {
profile: null,
profiles: null,
loading: false
};
export default function(state = initialState, action) {
switch (action.type) {
case PROFILE_LOADING:
return {
...state,
loading: true
};
case GET_PROFILE:
return {
...state,
profile: action.payload,
loading: false
};
case CLEAR_CURRENT_PROFILE:
return {
...state,
profile: null
};
default:
return state;
}
}
profileActions.js
import axios from "axios";
import {
GET_PROFILE,
PROFILE_LOADING,
CLEAR_CURRENT_PROFILE,
GET_ERRORS
} from "./types";
// Get current profile
export const getCurrentProfile = () => dispatch => {
dispatch(setProfileLoading());
axios
.get("/api/profile")
.then(res =>
dispatch({
type: GET_PROFILE,
payload: res.data
})
)
.catch(err =>
dispatch({
type: GET_PROFILE,
payload: {}
})
);
};
// Create Profile
export const createProfile = (profileData, history) => dispatch => {
axios
.post("/api/profile", profileData)
.then(res => history.push("/dashboard"))
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Profile loading
export const setProfileLoading = () => {
return {
type: PROFILE_LOADING
};
};
// Clear profile
export const clearCurrentProfile = () => {
return {
type: CLEAR_CURRENT_PROFILE
};
};
仪表板.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { getCurrentProfile } from "../../actions/profileActions";
class Dashboard extends Component {
componentDidMount() {
this.props.getCurrentProfile();
}
render() {
const { user } = this.props.auth;
const { profile, loading } = this.props.profile;
let dashboardContent;
if (profile === null || loading) {
dashboardContent = <h4>Loading</h4>;
} else {
dashboardContent = <h1>Hello</h1>;
}
return (
<div className="dashboard">
<div className="container">
<div className="row">
<div className="col-md-12">
<h1 className="display-4">Dashboard</h1>
{dashboardContent}
</div>
</div>
</div>
</div>
);
}
}
Dashboard.propTypes = {
getCurrentProfile: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
profile: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
profile: state.profile,
auth: state.auth
});
export default connect(
mapStateToProps,
{ getCurrentProfile }
)(Dashboard);
App.js
import React, { Component } from "react";
import "./App.css";
import Navbar from "./components/layout/Navbar";
import Footer from "./components/layout/Footer";
import Landing from "./components/layout/Landing";
import Login from "./components/auth/Login";
import Register from "./components/auth/Register";
import { BrowserRouter as Router, Route } from "react-router-dom";
import jwt_decode from "jwt-decode";
import setAuthToken from "./utils/setAuthToken";
import { setCurrentUser, logoutUser } from "./actions/authActions";
import { clearCurrentProfile } from "./actions/profileActions";
import { Provider } from "react-redux";
import store from "./store";
import Dashboard from "./components/dashboard/Dashboard";
// Check for token
if (localStorage.jwtToken) {
// Set auth token header auth
setAuthToken(localStorage.jwtToken);
// Decode token and get user info and exp
const decoded = jwt_decode(localStorage.jwtToken);
// Set user and isAuthenticated
store.dispatch(setCurrentUser(decoded));
// Check for expired token
const currentTime = Date.now() / 1000;
if (decoded.exp < currentTime) {
// Logout user
store.dispatch(logoutUser());
// clear current profile
store.dispatch(clearCurrentProfile());
// Redirect to login
window.location.href = "/login";
}
}
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Navbar />
<Route exact path="/" component={Landing} />
<div className="container">
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/dashboard" component={Dashboard} />
</div>
<Footer />
</div>
</Router>
</Provider>
);
}
}
export default App;
store.js
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(...middleware),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
export default store;
【问题讨论】:
-
大量代码,我们在这里很难提供帮助。你能在
profileActions.js的getCurrentProfile...then()块内console.log(res.data)吗?您的前端是否成功从后端检索配置文件? -
@JacobMoore,你如何组合你的减速器?当您收到此错误时,没有
profile状态。所以,要么这里发生了奇怪的事情,要么州名不知何故弄乱了。 -
@JacobMoore,尽管我讨厌你添加 more 代码,但我认为你需要发布
./store来回答 @devserkan '问题 -
store和index.js可能在reducers目录中,如果他像我一样使用他的减速器:) -
我编辑了帖子并包含了商店。当我在 then 块中使用 console.log(res.data) 或在 catch 块中使用 console.log(err) 时,没有任何记录。
标签: reactjs redux react-redux