Question

I'm working on a React/Redux application. I receive a data object from the api resembling this:

const dataObj = [
  {
    id: 1,
    name: "Filo",
    activity: 9,
    info: {
      statusCode: 4
    }
  },
  {
    id: 2,
    name: "Spot",
    activity: 8,
    info: {
      statusCode: 2
   }
 }
];

I have to run the data through a series of conditional function to create dom elements at different points like this:

const getElementsIcons = dog => {
    const elementData = []

    elementData.push({...})

    if (dog.info.statusCode === ADOPTED_ID) {
        elementData.push({...})
    }
    if (dog.info.statusCode === PENDINGID) {
        elementData.push({...})
    }
    if (dog.info.statusCode === PENDING_ID && dog.activity === OTHER_VALUE) {
        elementData.push({...})
    }

    return elementData
}

However, does it make sense to have this conditional logic inline above, or should I create a 'class' like so:

function Dog(data) {
  this.name = data.name;
  this.isAdopted = data.statusCode === ADOPTED_ID;
  this.otherCondition =
    data.statusCode === PENDING_ID && data.activity === OTHER_VALUE;
}

Then deal with the modified data throughout the application?

If it makes sense to create a class, should I do this when I normalize the data from the api call where I store it in redux, or later on when I pass it to the react component that consumes the data?

Was it helpful?

Solution

If javascript were a pure object oriented programming language, I would have recommended to you to create an object to encapsulate data with behavior, since it's the very purpose of OOP. By doing that, you keep isolated the mutations applied to your objects.

But, javascript is also a functionnal programming language. In functionnal programming language, we do the opposite, we separate data from behaviors to favor functions composition. But to avoid the pitfalls of an Anemic Domain Model, you should ensure the immutability of your objects, to avoid accidental mutations.

All in all, I would not recommend you to create a specific class as an encapsulation mechanism but use a module instead, something like this :

// in /some/path/dog.js

const Dog = (theDogData) => {
  const isAdopted = data.statusCode === ADOPTED_ID;
  const otherCondition = data.statusCode === PENDING_ID && data.activity === OTHER_VALUE;
  return Object.freeze({
    isAdopted,
    otherCondition,
  });
}

module.exports = {
  Dog,
};

Using module instead of Class let you just require individual method without being tied to a real object. So if you want your Dog to be able to do some thing that many Animals can do (like eating), you can require this function from the Animal module. By doing so, if later on you need an animal that for whatever reason you don't need it to be able to "eat", you don't have to require this method. This protects you from the Gorilla / Banana problem and the Fragile Base Class problem. I can only suggest you to learn more about that in the excellent post Composition over inheritance from Mattias Petter Johansson. It's very well explained !

OTHER TIPS

Generally, given two or more things that work together think about making an object to encapsulate that interaction. I think that's the case here - dataObj objects yield Dog objects which are used to create elementData (DOM elements).


should I do this when I normalize the data from the api call where I store it in redux, or later on when I pass it to the react component that consumes the data?

Generally raw data is best converted up front into "problem domain context" object(s). Thus your application code is totally unaware of the raw data per se.

That data conversion should ideally be an object, and depending on the complexity of that conversion, uses one or more other objects (such as Dog).


You are creating Dog objects to hold all of a given dog's information as derived from the raw dataObj. So calculate "what DOM element" there too.

Licensed under: CC-BY-SA with attribution
scroll top