1
\$\begingroup\$

I have a file where I keep some initial values for some form fields base on field type. Some of them are primitive values, like '' or 0 or false but some of them are non-primitive reference values, like [] or {}. For example:

INITIAL_VALUES.js

const INITIAL_VALUES= {
  SINGLE_CHOICE: '',
  MULTIPLE_CHOICE: [],
  OBJECT: {},
  BOOLEAN: false,
  NUMBER: 0,
  STRING: ''
};

export default INITIAL_VALUES;

The fact is that I have to be careful when using non-primitive initial values, because since they come as reference, I might change them, and get them a second time with some residual value, instead of being empty.

I've tought about some options to deal with this:


OPTION #1

Make the INITIAL_VALUES.js export a function that returns the new values object and call that function inside my component.

Example:

getInitialValues.js

function getInitialValues() {
  return({
    SINGLE_CHOICE: '',
    MULTIPLE_CHOICE: [],
    OBJECT: {},
    // and so on...
  });
}

export default getInitialValues;

SomeComponent.js

import getInitialValues from './getInitialValues'

function SomeComponent() {
  const INITIAL_VALUES = getInitialValues();
}

OPTION #2

Keep the initial values as an object and everytime I use them, I need to check if it's a non-primitive and create a new one (instead of using the same reference from INITIAL_VALUES).

Example:

SomeComponent.js

myVariable = INITIAL_VALUES[fieldType];

if (Array.isArray(myVariable)) {
  myVariable = [...myVariable];                   // CREATE A NEW ARRAY
}
else if (typeof(myVariable)  === 'object') {
  myVariable = {...myVariable};                   // CREATE A NEW OBJECT
}

OPTION #3

Use only non-primitive values. And set null instead of empty arrays [] and empty objects {}.

Example:

INITIAL_VALUES.js

const INITIAL_VALUES= {
  SINGLE_CHOICE: '',
  MULTIPLE_CHOICE: null,
  OBJECT: null,
  BOOLEAN: false,
  NUMBER: 0,
  STRING: ''
};

But doing so, whenever I try to populate those fields, I'll need to check if the object/array exists, and create it if it doesn't.

Example

SomeComponent.js

function pushValueToArrayField(newValue) {
  setState((prevState) => {
    const aux = {...prevState};
    if (aux.someArrayField === null) {
      aux.someArrayField = [];
    }
    aux.someArrayField.push(newValue);
    return aux;
  });
}

What is my best option here?

\$\endgroup\$
7
  • 2
    \$\begingroup\$ "I have a file" How big? What does your current code look like, exactly? On Code Review, we don't deal well with hypotheticals. Please take a look at the help center and consider what you really want to ask here. \$\endgroup\$ – Mast Aug 1 '19 at 10:14
  • \$\begingroup\$ The INITIAL_VALUES.js file is my exact file. And the options are the consequences that I'll have to embrace whatever road I take. \$\endgroup\$ – cbdeveloper Aug 1 '19 at 10:21
  • \$\begingroup\$ Why don't you have the default for your textarea component in your textarea-component.js, for your multiple choice component in multiple-choice-component.js, etc? \$\endgroup\$ – Mohrn Aug 1 '19 at 14:38
  • \$\begingroup\$ @Mohrn because then my initial values would be hard coded across multiple files. And I might want to change them at some point. \$\endgroup\$ – cbdeveloper Aug 1 '19 at 14:50
  • 1
    \$\begingroup\$ Cant you just freeze it? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… \$\endgroup\$ – konijn Aug 1 '19 at 18:04
0
\$\begingroup\$

So here's what I've ended up doing:

INITIAL_VALUES.js

function GET_FEATURE_TYPES_INITIAL_VALUES() {
  const FEATURE_TYPE_INITIAL_VALUES = {
    SINGLE_CHOICE: '',
    MULTIPLE_CHOICE: [],
    BOOLEAN: false,
    NUMBER: 0,
    STRING: ''
  };
  return FEATURE_TYPE_INITIAL_VALUES;
}

function GET_FILTER_TYPES_INITIAL_VALUES() {
  const FILTER_TYPE_INITIAL_VALUES = {
    NUMBER_RANGE_ALLOW_MULTIPLE: [],
    NUMBER_ACUM_RANGE_ALLOW_SINGLE: [],
    SINGLE_CHOICE_ALLOW_SINGLE: [],
    SINGLE_CHOICE_ALLOW_MULTIPLE: [],
    MULTIPLE_CHOICE_ALLOW_MULTIPLE: [],
    BOOLEAN_ALLOW_MULTIPLE: [],
    STRING_ALLOW_MULTIPLE: []
  };
  return FILTER_TYPE_INITIAL_VALUES;
}

function GET_FIELD_TYPES_INITIAL_VALUES() {
  const FIELD_TYPE_INITIAL_VALUES = {
    STRING_FIELD: '',
    BOOLEAN_FIELD: '',
    NUMBER_FIELD: 0,
    ARRAY_STRINGS_FIELD: [],
    ARRAY_OBJECTS_FIELD: [],
    OBJECT_FIELD: {}
  };
  return FIELD_TYPE_INITIAL_VALUES;
}

export {
  GET_FEATURE_TYPES_INITIAL_VALUES,
  GET_FILTER_TYPES_INITIAL_VALUES,
  GET_FIELD_TYPES_INITIAL_VALUES
};

SomeComponent.js

import { GET_FEATURE_TYPES_INITIAL_VALUES } from '@constants/INITIAL_VALUES';

function SomeComponent() {
  const FEATURE_TYPES_INITIAL_VALUES = GET_FEATURE_TYPES_INITIAL_VALUES();

  // FRESH NEW INITIAL_VALUES AVAILABLE ON EVERY RENDER
}

\$\endgroup\$
1
  • \$\begingroup\$ This neither follows best practices for React (defaultProps) nor for Javascript (camel case). \$\endgroup\$ – Mohrn Aug 1 '19 at 21:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.