React 18 - 无法使用 axios 和 redux 读取未定义的属性
React 18 - Cannot read properties of undefined with axios and redux
我正在尝试使用 redux 和 axios 从 API 获取信息。但是在我的组件中,我收到以下错误。
我的 package.json
里有这个
"dependencies": {
"autoprefixer": "^10.4.7",
"axios": "^0.27.2",
"postcss": "^8.4.13",
"prettier": "^2.6.2",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-redux": "^8.0.1",
"react-scripts": "5.0.1",
"redux": "^4.2.0",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.4.1",
"tailwindcss": "^3.0.24",
"web-vitals": "^2.1.4"
}
我尝试遵循的结构是 Redux 和 Redux-thunk。
- axios文件夹是axios客户端,APIURL
- 家是主成分
store.js
import thunk from 'redux-thunk';
import { applyMiddleware, createStore } from 'redux';
import rootReducer from './reducers';
import { composeWithDevTools } from 'redux-devtools-extension';
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware)),
);
export default store;
financesActions.js
import axiosClient from '../../config/axios'; //axios connection with API
import { FINANCES_ERROR, GET_FINANCES } from '../types'; //just constants
export const getFinances = () => async (dispatch) => {
try {
const response = await axiosClient.get('/api/finance'); //axiosClient has the rest of the URL and it's working
dispatch({
type: GET_FINANCES,
payload: response.data,
});
} catch (error) {
dispatch({
type: FINANCES_ERROR,
payload: console.error(error),
});
}
};
financeReducer.js
import { GET_FINANCES } from '../types';
const initialState = {
finances: [],
};
export const financeReducer = (state = initialState, action) => {
switch (action.type) {
case GET_FINANCES:
return {
...state,
finances: action.payload,
};
default:
return state;
}
};
index inside reducer 文件夹
import { combineReducers } from 'redux';
import { financeReducer } from './financeReducers';
export default combineReducers({
finances: financeReducer,
});
来自 src root 的索引文件包含来自 react-redux 的 Provider 以及我创建的商店:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
import { Provider } from 'react-redux';
import store from './store/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
);
最后,当我尝试使用 API 并获取信息时,在 Home 组件中。
import { connect } from 'react-redux';
import { getFinances } from '../../store/actions/financesActions';
import { useEffect } from 'react';
const Home = () => {
const { finances } = this.props.finances;
useEffect(() => {
this.props.getFinances();
console.log(finances);
}, []);
return (
<p>Hey</p>
);
};
const mapStateToProps = (state) => ({ finances: state.finances });
export default connect(mapStateToProps, { getFinances })(Home);
最后,我尝试将来自 react-redux 的连接与道具一起使用。我找到了一些我遵循的代码,但使用的是旧版本的 React。原代码如下:
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {getUsers} from '../store/actions/usersAction'
class users extends Component {
componentDidMount(){
this.props.getUsers()
}
render() {
const {users} = this.props.users
console.log(users)
return (
<div>
{users.map(u =>
<React.Fragment key={u.id}>
<h6 >{u.name}</h6>
</React.Fragment>
)}
</div>
)
}
}
const mapStateToProps = (state) => ({users:state.users})
export default connect(mapStateToProps, {getUsers})(users)
我知道原始代码使用的是 DidMount 和以前 React 版本中的旧东西。这就是我使用 useEffect Hook 更改它的原因。但是缺少了一些东西,我认为它与 reducer 文件中的调度函数有关。或者也许我不能使用那些道具。
我做错了什么?
Home
是功能组件,而不是 class 组件。您不需要 this
来访问道具。它们像函数参数一样被送入组件。您可能在从 class 组件迁移时错过了这一点 -
import { getFinances as getFinancesAction } from '../../store/actions/financesActions';
const Home = ({
finances,
getFinances,
}) => {
useEffect(() => {
getFinances();
}, []);
return (
<p>Hey</p>
);
};
const mapStateToProps = (state) => ({ finances: state.finances });
export default connect(mapStateToProps, { getFinances: getFinancesAction })(Home); //
注意 - 我在导入时使用了别名 getFinances
,否则文件将有两个同名的函数。
我正在尝试使用 redux 和 axios 从 API 获取信息。但是在我的组件中,我收到以下错误。
我的 package.json
里有这个"dependencies": {
"autoprefixer": "^10.4.7",
"axios": "^0.27.2",
"postcss": "^8.4.13",
"prettier": "^2.6.2",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-redux": "^8.0.1",
"react-scripts": "5.0.1",
"redux": "^4.2.0",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.4.1",
"tailwindcss": "^3.0.24",
"web-vitals": "^2.1.4"
}
我尝试遵循的结构是 Redux 和 Redux-thunk。
- axios文件夹是axios客户端,APIURL
- 家是主成分
store.js
import thunk from 'redux-thunk';
import { applyMiddleware, createStore } from 'redux';
import rootReducer from './reducers';
import { composeWithDevTools } from 'redux-devtools-extension';
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware)),
);
export default store;
financesActions.js
import axiosClient from '../../config/axios'; //axios connection with API
import { FINANCES_ERROR, GET_FINANCES } from '../types'; //just constants
export const getFinances = () => async (dispatch) => {
try {
const response = await axiosClient.get('/api/finance'); //axiosClient has the rest of the URL and it's working
dispatch({
type: GET_FINANCES,
payload: response.data,
});
} catch (error) {
dispatch({
type: FINANCES_ERROR,
payload: console.error(error),
});
}
};
financeReducer.js
import { GET_FINANCES } from '../types';
const initialState = {
finances: [],
};
export const financeReducer = (state = initialState, action) => {
switch (action.type) {
case GET_FINANCES:
return {
...state,
finances: action.payload,
};
default:
return state;
}
};
index inside reducer 文件夹
import { combineReducers } from 'redux';
import { financeReducer } from './financeReducers';
export default combineReducers({
finances: financeReducer,
});
来自 src root 的索引文件包含来自 react-redux 的 Provider 以及我创建的商店:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
import { Provider } from 'react-redux';
import store from './store/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
);
最后,当我尝试使用 API 并获取信息时,在 Home 组件中。
import { connect } from 'react-redux';
import { getFinances } from '../../store/actions/financesActions';
import { useEffect } from 'react';
const Home = () => {
const { finances } = this.props.finances;
useEffect(() => {
this.props.getFinances();
console.log(finances);
}, []);
return (
<p>Hey</p>
);
};
const mapStateToProps = (state) => ({ finances: state.finances });
export default connect(mapStateToProps, { getFinances })(Home);
最后,我尝试将来自 react-redux 的连接与道具一起使用。我找到了一些我遵循的代码,但使用的是旧版本的 React。原代码如下:
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {getUsers} from '../store/actions/usersAction'
class users extends Component {
componentDidMount(){
this.props.getUsers()
}
render() {
const {users} = this.props.users
console.log(users)
return (
<div>
{users.map(u =>
<React.Fragment key={u.id}>
<h6 >{u.name}</h6>
</React.Fragment>
)}
</div>
)
}
}
const mapStateToProps = (state) => ({users:state.users})
export default connect(mapStateToProps, {getUsers})(users)
我知道原始代码使用的是 DidMount 和以前 React 版本中的旧东西。这就是我使用 useEffect Hook 更改它的原因。但是缺少了一些东西,我认为它与 reducer 文件中的调度函数有关。或者也许我不能使用那些道具。
我做错了什么?
Home
是功能组件,而不是 class 组件。您不需要 this
来访问道具。它们像函数参数一样被送入组件。您可能在从 class 组件迁移时错过了这一点 -
import { getFinances as getFinancesAction } from '../../store/actions/financesActions';
const Home = ({
finances,
getFinances,
}) => {
useEffect(() => {
getFinances();
}, []);
return (
<p>Hey</p>
);
};
const mapStateToProps = (state) => ({ finances: state.finances });
export default connect(mapStateToProps, { getFinances: getFinancesAction })(Home); //
注意 - 我在导入时使用了别名 getFinances
,否则文件将有两个同名的函数。