I'm trying to get information from an API with redux and axios. But in my component I'm receiving the following error.
I have this in my 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"
}
The structure that I'm trying to follow is with Redux and Redux-thunk.
- Axios folder is the axios client with the API URL
- Home is the principal component
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's folder
import { combineReducers } from 'redux';
import { financeReducer } from './financeReducers';
export default combineReducers({
finances: financeReducer,
});
The index file from src root has the Provider from react-redux with the store I created:
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>,
);
Finally, in the Home component when I'm trying to consume the API and bring the information.
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);
At the end I'm trying to use the connect from react-redux with the props. I had found some code that I followed but with an older version of React. The original code was the following:
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)
I know the original code is using DidMount and older things from previous React versions. That's why I change that with the useEffect Hook. But something is missing, I think it's something with dispatch functions from the reducer file. Or maybe I can't use those props.
What am I doing wrong?
CodePudding user response:
Home
is a functional component, not a class component. You do not require this
to access props. They are fed into the component like function parameters. You probably missed that while migrating from class components -
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); //
NOTE - I have used an alias while importing getFinances
, else the file would have had two functions with the same name.