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。

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,否则文件将有两个同名的函数。