peiting sun
peiting sun

Reputation: 53

state in redux store change but component not change in view

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

Answers (1)

Sharzad Gh
Sharzad Gh

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

Related Questions