I have an issue with my redux. This is the first time I am using it in React. I have managed to successfully use it for logging and registering users. However, I have an array of objects created on backend which I am fetching with axios. Axios logs the data and my action creator also logs data in payload. However, it does not update my new state. I have no idea what I'm doing wrong as I tried it exactly the same way as with my login and register states, however these were only boolean values. I have googled and searched for a solution. I tried mapping new array, Object.assign and many others but I can't seem to get it working. Is there any special way on creating new array in state? or can I just assign it action.payload? I appreciate all help
// store.js
import { applyMiddleware, createStore } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
import reducer from './reducers/reducer';
const middleware = applyMiddleware(logger, thunk);
export default createStore(reducer, middleware);
// rootReducer.js
import { combineReducers } from 'redux';
import registerReducer from './registerReducer';
import loginReducer from './loginReducer';
import productsReducer from './products';
export default combineReducers({
registerReducer,
loginReducer,
productsReducer
});
// productsReducer // I believe sth must be wrong here
import { SHOW_PRODUCTS, SELECT_PRODUCT } from '../actions/products';
const initialState = {
productsList: []
};
const productsReducer = (state = initialState, action) => {
switch (action.type) {
case SHOW_PRODUCTS:
return {...state, productsList: action.payload}
}
return state;
}
export default productsReducer;
// actions.js
import { SHOW_PRODUCTS, SELECT_PRODUCT } from './constants';
export function showProducts(products) {
return {
type: SHOW_PRODUCTS,
payload: products
};
}
// component.js
import React, { Component } from 'react';
import axios from 'axios';
import { connect } from 'react-redux';
import ProductsList from './ProductsList';
import { showProducts } from '../actions/products';
class Home extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.getProducts();
}
render() {
return(
<div>Home Page
<ProductsList />
</div>
)
}
}
const mapStateToProps = (state) => {
return {
productsList: state.productsReducer.productsList
};
}
const mapDispatchToProps = (dispatch) => {
return {
getProducts: () => {
axios.get('http://localhost:5000/product/list')
.then((res) => {
console.log(res.data);
dispatch(showProducts(res.data))
})
.catch(err => console.log(err))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Home);
I am also including a link to an image with my redux logger.
https://i.stack.imgur.com/bTnYh.png
There's probably a very small, stupid mistake in here as I'm quite new to React and completely new to Redux
You have a mistake, and I don't know if you a linter but in productsReducer.js
you are importing constants
from actions
when it should be from constants
:
import { SHOW_PRODUCTS, SELECT_PRODUCT } from '../actions/constants'; // <- from constants instead
const initialState = {
productsList: []
};
const productsReducer = (state = initialState, action) => {
switch (action.type) {
case SHOW_PRODUCTS:
return {...state, productsList: action.payload}
}
return state;
}
export default productsReducer;
So your reducer
shouldn't be actually taken the proper case
since it is undefined
and It will so return the initial state.
I believe in mapStateToProps
you're going to want to do the following:
const mapStateToProps = (state) => {
return {
productsList: state.productsList
};
}
To confirm productsList
being passed through, can you add in a simple loop to the render
function of component.js
like below:
render() {
const { productsList } = this.props;
return(
<div>
Home Page
{productsList.map((product, index) => (
<div key={index}>{product.PROPERTY_NAME_HERE}</div>
))}
</div>
)
}
The way I do it with my reducer is
import { SHOW_PRODUCTS, SELECT_PRODUCT } from '../actions/products';
const initialState = {
productsList: []
};
const productsReducer = (state = initialState, action) => {
switch (action.type) {
case SHOW_PRODUCTS:
let nextState = {...state};
nextState.productsList = action.payload
return nextState;
}
return state;
}
export default productsReducer;
Try this way:
componentWillMount() {
this.getProducts();
}
getProducts() {
axios.get('http://localhost:5000/product/list')
.then((res) => {this.props.showProducts(res.data);})
.catch(err => console.log(err));
}
const mapDispatchToProps = dispatch => ({
showProducts: (data) => {
dispatch(showProducts(data));
},
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.