Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React & Reselect selector claims state is the same after update

I am implementing Reselect in my project and have a little confusion on how to properly use it. After following multiple tutorials and articles about how to use reselect, I have used same patterns and still somethings dont work as expected.

My selector:

const getBaseInfo = (state) => state.Info;
const getResources = (state) => state.Resources;

export const ASelector = createSelector(
  [getBaseInfo, getResources],
  (items, resources) => { 
    let result = {};
    for(const item in items) {
      console.log(item);
      result[item] = _.pick(items[item], ['Title', 'Type', 'Beginning', 'minAmount', 'Address'])
    }
    for(const item in resources) {
      console.log(item);
      result[item] = {...result[item], firstImage: resources[item].firstImage}
    }
    return result;
  }
);

mapStateToProps component:

function mapStateToProps(state) {
  console.log(state);
  return { 
    gridInfo: ASelector(state)
  }
}

Now at first my initial state is:

state = { Info: {}, Resources: {} }

My Reducer:

const Info = ArrayToDictionary.Info(action.payload.data.Info);
  const Resources = ArrayToDictionary.Resources(action.payload.data.Info);
  let resourcesKeys = Object.keys(Resources);
  let infoKeys = Object.keys(Info);
  let temp = { ...state };
  let newInfo;

  for (let item of infoKeys) {
    newInfo = {
      Title: Info[item].Title,
      Type: Info[item].Type,
      BeginningOfInvesting: Info[item].BeginningOfInvesting,
      DateOfEstablishment: Info[item].DateOfEstablishment,
      pricePerUnit: Info[item].PricePerUnit,
      minUnits: Info[item].MinUnits,
      publicAmount: Info[item].PublicAmount,
      minInvestmentAmount: Info[item].MinInvestmentAmount,
      EinNumber: Info[item].EinNumber,
      Address: Info[item].Address,
      Status: Info[item].Status,
      Lat: Info[item].Lat,
      Lng: Info[item].Lng,
      CurrencySymbol: Info[item].CurrencySymbol,
      Publicity: Info[item].Publicity
    }
    temp.Info[item] = { ...temp.Info[item], ...newInfo }
  }
  for (let item of resourcesKeys) {
    temp.Resources[item] = { ...temp.Resources[item], ...Resources[item] }
  }
  return temp;

As a component renders with the initial state, I have an action pulling data from api and saving it accordingly into the state inside reducers.

Now my state is changed, but after debugging a little into reselects code, I found in the comparison function that the old and new states are the same. Suddenly my "old" state became already populated with the newState data and it of course failing the comparison as they became the same.

Is there anything wrong with my selectors?

I have really tried to use it as the documentation states, but still cant understand how to solve my little issue.

Thank you very much for reading and helping!

like image 331
Kiper Avatar asked Sep 05 '18 07:09

Kiper


People also ask

What is React used for?

It is a library that allows us to create native mobile apps in Android and iOS using React. js. In 2016, with version 15, React. js started using Semantic Versioning.

Is React for HTML or js?

To get an overview of what React is, you can write React code directly in HTML. But in order to use React in production, you need npm and Node. js installed.

Is React better or Angular?

React is better than Angular due to it's virtual DOM implementation and rendering optimizations. Migrating between React's versions is quite easy, too; you don't need to install updates one by one, as in the case of Angular. Finally, with React, developers have myriads of existing solutions they can use.

What is in React means?

1 : to exert a reciprocal or counteracting force or influence —often used with on or upon. 2 : to change in response to a stimulus. 3 : to act in opposition to a force or influence —usually used with against. 4 : to move or tend in a reverse direction. 5 : to undergo chemical reaction.


1 Answers

It looks like the temp.Info[item] and temp.Resources[item] lines are mutating the existing state. You've made a shallow copy of the top level, but aren't correctly copying the second level. See the Immutable Update Patterns page in the Redux docs for an explanation of why this is an issue and what to do instead.

You might want to try using the immer library to simplify your immutable update logic. Also, our new redux-starter-kit library uses Immer internally.

like image 143
markerikson Avatar answered Oct 02 '22 23:10

markerikson