reselect, Where do I put the calculate derive data logic?

286 views Asked by At

Recently, I start to learn reselect, and try to use it to my project.

But, I'm doubtful about where should I put the code that calculates the derived data.

Below is my code snippet, I think I put formatDate calcDayLeftFromNow setDeriveData logic to my reducer will also be fine.

I do the derive data calculate in my reducer will also be fine.

If I do this, it seems there is no reason to use reselect.

function formatDate(millisecond) {
  let d = new Date(millisecond);
  let dateArr = [d.getFullYear(), d.getMonth() + 1, d.getDate()];
  let date = dateArr.join('.');
  return date;
}

function calcDayLeftFromNow(endTimeNum) {
  const timeDiff = endTimeNum - new Date().getTime();
  const daysDiff = Math.ceil(timeDiff / (1000 * 3600 * 24));
  return daysDiff;
}

function setDeriveData(coupons) {
  return Object.values(coupons).map((coupon, index) => {
    coupon.startDate = formatDate(coupon.startTimeNum);
    coupon.endDate = formatDate(coupon.endTimeNum);
    coupon.dayLeft = calcDayLeftFromNow(coupon.endTimeNum);
    return coupon;
  });
}

const mapStateToProps = state => {
  const { coupons, current_tab, result, page } = state.yao_coupon;
  const newCoupons = setDeriveData(coupons);

  return {
    coupons: newCoupons,
    current_tab,
    result,
    page
  };
};
1

There are 1 answers

2
Abdellah Stands with Gaza On BEST ANSWER

It's common to put your selector's code in your container component. Or if you don't want to split container from presentational, just put it in your component.

Selectors' role is to compute derived data from the state (store).

Whereas reducers specify how the application's state changes in response to an action.

So they serve a very different role in your app.

In the Reselect readme, they're putting everything in one file just to showcase its use in the simplest way.

Here is a common folder structure that might help you make sense of this:

| reducers #folder
    date.js
| components #folder
   | Clock #folder
     ClockContainer.js #contains mapStateToProps (and your selectors) and mapDispatchToProps
     Clock.js #the clock component

Some people choose to put the selectors in a separate file. But it's up to you to decide. For example, you can put your selector in your container component and only move it to a separate file if it gets big. Another reason to move it to a separate file is in the event you need that same selector throughout parts of the app. (credits: @kwelch)

Edit

when I fetch bookList data from server, I calculate the derivedPrice in my FETCH_SUCCESS reducer

Calculating the derived price in your reducer will make it highly coupled with the api call, and you won't be able to use the dispatched action elsewhere. My suggestion is to move this calculation out of the reducer and calculate the derivedPrice before dispatching the action.