Reputation: 53
I am trying to learn react-redux by making a simple product listing page, I used the redux dev tool in chrome, the state in store change properly but my product list component didn't rerender when the state changes. below is my code in my store/index.js
import rootReducer from "../reducers/productsReducer";
import { createStore, applyMiddleware,compose } from "redux";
import thunk from "redux-thunk";
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export const store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunk)));
in my index.js
import { store } from "./store";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
in my App.js
function App() {
return (
<div className='App'>
{/* <ProductList /> */}
<Search />
<Dropdown />
<ProductList />
</div>
);
}
export default App;
my rootReducer for sorting
const initialState = [];
const fetchProduct = (state = initialState, action) => {
switch (action.type) {
case FETCH_PRODUCT:
// console.log("fetchproduct is activated", action.payload);
return action.payload;
case SET_SORT:
const selectedSort = action.payload.sort;
console.log(state)
const newState = { ...state ,products :
(selectedSort == SORT_FILTER.PRICE_HIGH_TO_LOW)
? state.products.sort((a, b) => b.displayPrice - a.displayPrice)
: state.products.sort((a, b) => a.displayPrice - b.displayPrice)};
console.log(newState.products);
return newState.products;
default:
return state;
}
};
const rootReducer = (state, action) => {
return {
products: fetchProduct(state, action),
};
};
export default rootReducer;
my Dropdown component for selecting sorting type
const Dropdown = (props) => {
const updateSortByFilter = (e) => {
props.setSort(e.target.value);
};
return (
<div>
<label>Sort By:</label>
<select onChange={updateSortByFilter}>
<option value='-'>-</option>
<option value='price low to high'>price low to high</option>
<option value='price hight to low'>price hight to low</option>
</select>
</div>
);
};
export default connect(null, { setSort })(Dropdown);
the setSort action looks like this:
export default (sort) =>
{
return async(dispatch) =>{
dispatch({
type: SET_SORT,
payload: { sort },
});
}
}
and my productlist component looks like this
const ProductList = (props) => {
return (
<section>
{console.log(props.products)}
<h2>Products</h2>
{props.products.map(product =>
<div key={product.goodsSn}>
<h3>{product.goodsTitle}</h3>
<p>{product.description}</p>
<p> {product.displayPrice}</p>
</div>
)}
</section>
);
};
const mapStateToProps = (state)=>({
...state,
})
export default connect(mapStateToProps)(ProductList);
I tried to use mapStatetoprops for product list components,but seems every time even "products" in state change, the list still stay, and not changing order based on the selected value in the dropdown list (price from high to low / price from low to high), it stays the order that comes from the search function(which is simply fetching data from API and return a new product list in state.
Upvotes: 3
Views: 97
Reputation: 158
I implement your code on sandbox and figure out some errors
1- setSort
doesn't have name in your code
export const setSort = (sort) => {
return async (dispatch) => {
let res = await axios.get("https://fakestoreapi.com/products");
//return res of fetch data to payload
dispatch({
type: "SET_SORT",
payload: { sort, products: res.data }
});
};
};
2-change value
of <option>
to valid and without space
<select onChange={updateSortByFilter}>
<option value='-'>-</option>
<option value='LTH'>price low to high</option>
<option value='HTL'>price hight to low</option>
</select>
3- return res of fetch data to payload
in action (if you fetch data of products)
dispatch({
type: "SET_SORT",
payload: { sort, products: res.data }
});
4- change reducer
case "SET_SORT":
const selectedSort = action.payload.sort;
const newState = {
...state,
products: action.payload.products
};
selectedSort === "HTL"
? newState.products.sort((a, b) => b.price - a.price)
: newState.products.sort((a, b) => a.price - b.price);
return newState.products;
codeSandbox : here is my code
Upvotes: 1