0

i have an array of json object which contains title and array of subtitles and i have a select option where am storing the title lists and i made a loop on the subtitles array so i can add inputs depending on the subtitles length the problem is that when i select first item it works fine but when i select the second item from the dropdown list it doesn't see the new update of the array so it shows me an error of undefined because the state didn't update correctly i didn't know how to solve it

here is my array :

     constructor(props) {
      super(props);
      this.state = {
        Modules_SubModules_Array: [{
          "Module": "",
          "SubModules": []
        }],
      };
    }

and then there is the function that i execute when i select item from dropdown list :

  Affect_Module_Submodule = (currentModuleTitle, index) => {
    if (
      this.state.Modules_SubModules_Array.findIndex(
        item => item.Module == currentModuleTitle
      ) < 0
    ) {
      this.state.Modules_SubModules_Array.splice(index, 1, {
        Module: currentModuleTitle,
        SubModules: []
      });
      this.setState({
        Modules_SubModules_Array: this.state.Modules_SubModules_Array
      });
    }
  };

and there is the loop that i use :

  values.Modules_SubModules_Array[this.state.selectedIndex].SubModules.map(
    (subModule, index2) => {
      return (
        <div key={index2}>
          <TextFields
            style={{ marginLeft: "15%" }}
            defaultValue={subModule}
            hintText="SubModule Title"
            floatingLabelText="SubModule Title"
            onChange={e =>
              this.props.handleSubModuleChange(
                e,
                index2,
                this.state.selectedIndex,
                this.state.result,
                values.subModuleTitle
              )
            }
          />
          <input
            type="button"
            value="remove"
            onClick={() =>
              this.props.removeSubModule(index2, this.state.result)
            }
          />
          <br />
          <br />
        </div>
      );
    }
  );

the selectIndex is the index of the json object which contains the title that i selected from the dropdown list

so when i select a first item from the select the loop works and when i try to change to a second item from the select it won't work it tells me cannot read SubModules of undefined because in my console it prints undefined then it prints the new state so of course it won't work because he sees undefined at first didn't know how to solve it

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
AOUADI Slim
  • 299
  • 1
  • 8
  • 27
  • I'm confused by your `Affect_Module_Submodule` function. `findIndex` returns the first element in the array that matches the condition. However, your condition is if the (`item.Module == currentModuleTitle) < 0`. `item.Module == currentModuleTitle` will return a boolean (true or false) which you're then comparing to be less than 0, which it never should. Or am I missing something here? – technicallynick Aug 16 '19 at 16:12
  • @Clrity findIndex does not return the index of item that is equal to currentModuleTitle ? – AOUADI Slim Aug 16 '19 at 16:14
  • am testing if i didn't find that item which is equal to currentModuletitle then i do the splice – AOUADI Slim Aug 16 '19 at 16:15
  • @AOUADISlim you're mutating state directly, which is a bad idea. You need to make a cop first and then splice it and after that set it on state. – Clarity Aug 16 '19 at 16:17
  • @Clarity u mean like this const list = this.state.Modules_SubModules_Array; list.splice(index, 1, { "Module": currentModuleTitle, "SubModules": [] }) this.setState({ Modules_SubModules_Array: list }) – AOUADI Slim Aug 16 '19 at 16:21
  • Possible duplicate of [Correct modification of state arrays in ReactJS](https://stackoverflow.com/questions/26253351/correct-modification-of-state-arrays-in-reactjs) – Emile Bergeron Aug 16 '19 at 20:03

1 Answers1

1

Array#splice mutates the array and since you're applying it to your state, you mutate it directly. You need to make a copy of state first, apply the changes to the copy and then set it on the state:

Affect_Module_Submodule = (currentModuleTitle, index) => {
  let copyArray = this.state.Modules_SubModules_Array.concat();

  if (copyArray.findIndex(item => item.Module == currentModuleTitle) < 0) {
    copyArray.splice(index, 1, {
      Module: currentModuleTitle,
      SubModules: []
    });

    this.setState({
      Modules_SubModules_Array: copyArray
    });
  }
};
Clarity
  • 10,730
  • 2
  • 25
  • 35