2

I have a functional React component with useState hooks, and I have an array with five textinput fields. The values of the input fields are registered in the state in an array. The problem is, that I want to update the inputfields array with an onChange listener every time I input something. However, once I load the page, the function (onChange listener) is executed immediately in an endless loop... why is that?

const addDublette = props => {
    // constructor(props) {
    //     super(props);
    //     this.textInput1 =  React.createRef();
    // }
    const [actualState, changeState] = useState({
        showInputField: false,
        dublettenIDs: [],
        errorMessage: '',   
        inputFields: ['','','','',''],
    });  ....

My method to update input values in state:

const handleDoublettenIDs = (event,index) => {     
        let idnumber = event.target.value;
        let newInputFields = [...actualState.inputFields];
        newInputFields.splice(index,1, idnumber);
        console.log(newInputFields);
        if (isNaN(idnumber)) {
            changeState({...actualState, errorMessage: 'ID is not a number'})
        } if (idnumber > 2147483647) {
            changeState({...actualState, errorMessage: 'Number can not be bigger than 2147483647!'})
        }        
        else {
            changeState({...actualState, inputFields: newInputFields, errorMessage: '' });
        }      
    }

My return render method:

return (
<p>       
                {

                    actualState.inputFields.map((val,index) => (                        
                        <InputElement key={index} elemValue = {val} name={"input" +  index} onChangeListener={(event,index) => handleDoublettenIDs(event,index)} />
                        )
                    )
                }

                <p>{errorMessage}</p>
                <br />                    
                <p><button onClick = {handleInputs(props.anzeigeID)}>absenden</button></p>   
            </p>  ...)

I pass the onChangeListener method down to my InputElement components "onChange" method with the props.onChangeListener property...

const inputElement = (props) => (
    <p>
        <input 
            value ={props.elemValue}
            ref={props.reference}
            name={props.name}
            type="number" 
            max="2147483647"
            placeholder="Doubletten-ID" 
            onChange={props.onChangeListener}>            
        </input>
    </p>


)



export default inputElement

I think the problem could be in a circular update dependency loop, but I still have not found out where and how...

skyboyer
  • 22,209
  • 7
  • 57
  • 64
MMMM
  • 3,320
  • 8
  • 43
  • 80
  • try changing `onChange={props.onChangeListener}` to `onChange={props.onChangeListener.bind(this)}` – messerbill May 06 '19 at 10:34
  • What does your `handleInputs` function do? – Phillip May 06 '19 at 10:35
  • @Phillip, my handleInputs method is just another method to do some database post/fetch method after a button has been clicked with new data from input values – MMMM May 06 '19 at 10:37

2 Answers2

2

Problem is your onClick on button component where you execute the function

<p><button onClick = {handleInputs(props.anzeigeID)}>absenden</button></p>

The correct way is this

<p><button onClick = {() => handleInputs(props.anzeigeID)}>absenden</button></p>
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • hey thanks a lot, that actually was the real problem ;). I guess I was executing that function immediately doing a constant state updating... – MMMM May 06 '19 at 10:43
  • can you maybe clarify or give me a tip where I should use arrow functions and where I can just use normal functions ? I find it really confusing, because in Class components, I just pass a function property to the handler, e.g as "{this.functionname}" and sometime I have to pass an arrow function, because in functional components, I cant use this.functionname I have to use only "functionname" (without passing a reference) and then it will get executed immediately... which is totally confusing – MMMM May 06 '19 at 10:46
  • 1
    @user2774480 yes that happens when you perform state update during render cycle. You must note that when you write `fn()` it calls a function whereas if you write `fn` it assigns the reference to the event or prop or variable. Similarly an arrow function will create a new function and which when called will call the original method with some predefined arguments – Shubham Khatri May 06 '19 at 10:46
  • You must use arrow functions only when you want to pass a custom argument to the function when it is called and when you want to assign the function reference to something instead of calling it – Shubham Khatri May 06 '19 at 10:49
1

when you call a 'function()' like this, you're actually executing it. Otherwise, when you call a function by reference 'function', it will be executed when it's called by an event, like the click!

  • nice thanks, didn't know I was creating a new function reference by the arrow function syntax: `()=>fnct(param)` I thought it was like an event handler function being immediately executed ;) – MMMM Jul 10 '19 at 13:42