0

I would like to be able to store some form of dynamic structure in the state. Each input element calls the same function "handleFormInput". in "name" the input name is stored. In "value" the actual value.

After each change these values are stored in the state.

If the user now clicks on the form button, the function "handleForm" is called. This function checks the state and reacts accordingly.

My problem: I check the length of the array, which is always 0.

If I output everything via Console.log, however, I see the elements in the array, also correctly. What have I not considered?

Called on every input change made

    handleFormInput(event){
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        this.state.saveFormData[name] = value;
        

        this.setState({
            saveFormData : this.state.saveFormData
        }, () => {console.log(this.state.saveFormData)});
    }

Called when "Submitting"

    handleForm(){
        var l = 0;
        this.state.saveFormData.forEach(element => {
            l++; 
        });

        console.log(l); // output: 0


        if(this.state.saveFormData.length == 0){
            this.setState({ openNew: false })
            console.log(this.state.saveFormData);
        }else{
            console.log(this.state.saveFormData);
            alert('we found Data' + JSON.stringify(this.state.saveFormData));
        }
    }

Ouput of console.log

Array []
​
length: 0
​
ort: "asd"
​
<prototype>: Array []

Working Example in a Nutshell if you start with the input, the array is written to the console after each input. Stack Snippet already shows an empty array here. The console in the browser shows an array with one element but with a length of 0.

In the similar answers I find, it always has to do with the fact that the console does not map the exact moment of the array, but only shows a reference, and retrieves the data just in time when it is unfolded.

in my case it seems to behave differently. Since also in the console the array length of 0 is shown

function App() {
  return ( < DataEditor / > );
}

class DataEditor extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      data: [],
      def: [],
      defRaw: [],
      loaded: false,
      isLoading: false,
      openNew: false,
      editFormLoaded: false,
      editFormData: [],
      saveFormData: []
    }

  }

  handleFormInput(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.state.saveFormData[name] = value;

    console.log(this.state.saveFormData);

    this.setState({
      saveFormData: this.state.saveFormData
    });
  }

  handleForm() {


    if (this.state.saveFormData.length == 0) {
      this.setState({
        openNew: false
      })
      console.log(this.state.saveFormData);
    } else {
      console.log(this.state.saveFormData);
      alert('we found Data' + JSON.stringify(this.state.saveFormData));
    }
  }

  render() {
    return ( <
      div >
      <
      input type = "text"
      name = "ort"
      onChange = {
        (e) => this.handleFormInput(e)
      }
      /> <
      button type = "button"
      onClick = {
        () => this.handleForm()
      } > Test < /button> < /
      div >
    );
  }
}


ReactDOM.render( < App / > , document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Maik Thiele
  • 505
  • 2
  • 10
  • 1
    Where does the `ort: "asd"` output come from? I don't see that `console.log`. – T.J. Crowder Nov 17 '21 at 14:05
  • If you think or discover that this isn't the [linked issue](https://stackoverflow.com/questions/38660832/), please update your question with a [mcve] demonstrating the problem, ideally a **runnable** one using Stack Snippets (the `[<>]` toolbar button). Stack Snippets support React, including JSX; [here's how to do one](http://meta.stackoverflow.com/questions/338537/). And @ ping me so A) I can reopen the question, and B) I can try to help. :-) (Naturally you won't be able to submit a form, but you can mock that part.) – T.J. Crowder Nov 17 '21 at 14:06
  • So the issue is not the linked issue, the example does prove that, on a side not i think it's because the state object is an entirely managed system in react so `this.state.saveFormData[name] = value;` wont work, you need to grab a copy of it first (your effectively updating the state without setState and if a remember correctly react blocks that `let saveFormData = this.state.saveFormData; saveFormData[name] = value;` – Barkermn01 Nov 19 '21 at 01:34
  • @Barkermn01 thank you for your impressions. In the meantime, I think I'm on the track of the whole thing. An array is like everything else, an object in JavaScript. The way I supposedly add an object to the array is wrong. I only change a property of the object and do not add an iterable object. I could solve the problem by using ```jsObject.keys(obj).length``` for checking. If this is the best solution I don't know but functional enough for my needs at this point. – Maik Thiele Nov 22 '21 at 15:26
  • An Array is not an Object in JS, an Array is a Managed List so has methods, you can do .length, `let obj = {}; let arr = [];` an example that makes this clear is look for the method `forEach` only Arrays have forEach, Objects don't – Barkermn01 Nov 23 '21 at 22:47
  • @Barkermn01 can't agree on this. each array is indeed an object, but not every object is an array. And this is exactly the problem. I don't add an object using an array method, so the added value is assigned as a property of the object, but not as part of the array. That's why my previously mentioned way of counting the properties of the object works, and the normal .length method doesn't work. because it is a method of the array object and it returns the number of contents of the array, in my case 0. If I parse all properties of the object to an array and use length here, I get the number. – Maik Thiele Nov 24 '21 at 12:54
  • Ok, in the same way, that anything that is not primitive is an object, but this still does not change that you should not update the state objects or any properties of a state outside of setState doing so means that the React Schedular Management system is not updated, and can produce unexpected behaviors because React does not know whether or not it should be re-rendering the component, you should never update the state without using setState, also you should never set information into the state that is not used to inform rendering, that's what scope variables are for . – Barkermn01 Nov 24 '21 at 20:06

0 Answers0