[React]Making component state shorter[solved]

Hi everyone,

I need some advice so, I am here. I have a big state in my form component and the person I am working with would like I make it shorter and avoid repetitions (but some of the repetitions are due to using Material Design for Bootstrap framework). He suggests me to do some maps but I can’t imagine how I can do this and it seems a bit strange to me. But maybe I am wrong, as I am just a newbie for now.

In my opinion, I need to break the component in severals components, if I want the component state to be shorter. But, as my form component isn’t working at 100 % at the moment, if I need to do it, I will do it when everything is working.

So here is my big state :

const initState = {
hideIsClicked: false,
  isClicked: false,
  appEvaluation: true,
  appNiveau: true,
  appCertification: true,
  appExercice: true,
  appLangueConsigne: [
    {
      checked: false,
      text: "Japanese",
      value: "ja"
    },
    {
      checked: false,
      text: "French",
      value: "fr"
    },
    {
      checked: false,
      text: "English",
      value: "en"
    }
  ],
  appLangue: [
    {
      checked: false,
      disabled: false,
      text: "Japanese",
      value: "ja"
    },
    {
      checked: false,
      disabled: false,
      text: "French",
      value: "fr"
    },
    {
      checked: false,
      disabled: false,
      text: "English",
      value: "en"
    }
  ],
  appConsigne: "",
  questionElements: [
    {
      id: 0,
      questionElement: ""
    },
    {
      id: 1,
      questionElement:""
    },

    {
      id: 2,
      questionElement:""
    }
  ],
  reponseCorrecte: "",
  reponses: [
    {
      id : 0,
      reponse: ""
    },

    {
      id : 1,
      reponse: ""
    },
    {
      id : 2,
      reponse: ""
    },
    {
      id : 3,
      reponse: ""
    }
  ],
}

Do others solutions exist to make a state more simple ? What do you think ?:blush:

I would make appLangueConsigne, appLangue, questionElements, and responses all empty arrays in state. Then I would dynamically create each of these when needed. As far as maps go, I would create a lookup object for each language with the the abbreviations as the properties and the language names as the values of each property to be used to generate the arrays of objects at various times with the necessary values.

1 Like

Hi @Yumenotsuki, to be clear: which of the following does your colleague want?

  1. A more compact state at any point during the runtime
    1. This leads to slightly more code, and saves memory at the (possibly negligible) cost of more CPU cycles.
  2. A more compact description of initial state
    1. If this component’s entire state will be needed throughout it’s lifecycle, this could be what your coworker meant.

If (1), follow @RandellDawson’s advice alone, and make functions that return the needed piece of state given the inputs.
If (2), you can use Array.prototype.map to DRY out your code while still following the heart of approach 1.

The trick is to see what is being repeated and what is different.

So, in appLangueConsigne, you have all checked: false, and, as Randell mentioned, text and value properties whose values are a language’s name or two-letter abbreviation. Thus, you could create an array of language names & abbreviations and map from that ONTO the array of objects you currently have. You could (and probably should) take a hybrid approach using the lookup-table object strategy Randell suggested. To fully implement strategy 1 (cleaner, more reusable elsewhere in the component, or so that “data flows down” and can be reused appropriately in children, you want to functionalize the [].map() calls, turning the langKeys in the example (spoiler code) below into parameters that get passed, one at a time, to a function that returns the object, which can then be passed as the callback parameter you feed to .map().

const languageName = {
	fr: "French",
	ja: "Japanese",
	en: "English"
};

const langKeys = ['ja', 'fr', 'en'];

const initState = {
hideIsClicked: false,
  isClicked: false,
  appEvaluation: true,
  appNiveau: true,
  appCertification: true,
  appExercice: true,
  appLangueConsigne: langKeys.map(
		langKey => ({
			checked: false,
			text: languageName[langKey],
			value: langKey
		})
	),
  appLangue: langKeys.map(
		langKey => ({
			checked: false,
			disabled: false,
			text: languageName[langKey],
			value: langKey
		})
	),
  appConsigne: "",
  questionElements: Array(3).fill(null).map(
		(nullElem, i) => ({
			id: i,
			questionElement: ""
		})
	),
  reponseCorrecte: "",
  reponses: Array(4).fill(null).map(
		(nullElem, i) => ({
			id: i,
			reponse: ""
		})
	),
}
1 Like

@RandellDawson @vipatron Thank you very much for yours answers. :blush: I will study it and make mine with yours advice.

I think my coworker wants a more compact state because I need this component entire state to make my form working (and most of it are also needed to run the application.)

1 Like