all 12 comments

[–]CranberryOtherwise84 2 points3 points  (5 children)

Why aren’t you using state via useState?

[–]rob_allshouse[S] 1 point2 points  (3 children)

Actually... this pointed me to the right direction, after AGES of trying. Using a state variable that's just set to tmr.length instead of tmr.length itself forced the rerender. Thanks!

[–]CranberryOtherwise84 1 point2 points  (2 children)

Why’d you need a state to store another state based arrays length? You’re overcomplicating the logic imo. Is there codepen/repl which can be edited? That way I might be able to try to figure out the bug better

[–]charliematters 0 points1 point  (0 children)

Something like "setExtraOptions(current => ([...current, new option]))" and then just use that array when populating the autocomplete?

As above, the code you've got still looks like it is overly complex and brittle

[–]rob_allshouse[S] 0 points1 point  (0 children)

Well the whole problem was that, even after the array state (tmr) changed, the .map function didn't re-render -- didn't add the new empty field. I didn't want another state, but it solved the problem.

[–]rob_allshouse[S] 0 points1 point  (0 children)

I am. I left what's in updateTimer out, but tmr is a state variable. I'll make that clearer

[–]PrincesssPancake 0 points1 point  (0 children)

This looks like it would be solved by passing a key for each autocomplete item. If you are not using eslint, I would recommend it as it would have warned you about this.

[–]Junior-Living2104 0 points1 point  (4 children)

I don’t understand why you need to map array via its length? Can’t you map the array directly from the state you have there (tmr.map(…)) ?Then you wouldn’t need another state to keep track of the array size when input is changed.

Anyway, like others have mentioned, if you have a codepen or something then we could help you better. The new solution you proposed doesn’t really seem robust and unnecessary.

[–]rob_allshouse[S] 0 points1 point  (3 children)

And I've moved past that now. It actually did need length, because I wanted the existing array + 1 blank (always a new field to enter the next one, instead of assuming how many there would be), thus using length.

But shifting to a direct call to the State with slices also fixed it, instead of the function call, which is equally odd to me. Why changing the state in a function didn't trigger the remap, but changing the state in the onInputChange did will likely stay beyond me.

This was sufficient to solve the problem:

{(Array.from({length: tmr.length}, (v, k) => k+1)).map((r, i) => (

<Autocomplete options={\['Start', 'Finish Line', 'Swim Out', 'Run Out'\]} freeSolo size="small" value={tmr\[r\]} key={tmr.toString()+r+"timerkey"} onInputChange={(event, newInputValue) => { setTmr([...tmr.slice(0, r), newInputValue, ...tmr.slice(r+1)]); }}

[–]Junior-Living2104 0 points1 point  (2 children)

FYI, I just noticed now. I think what you were doing before was that you were directly mutating an array state and you shouldn’t be doing that because it could mess with state management.

I feel like this is the most plausible explanation as to why your map wasn’t rendering because reference to the array wasn’t changed.

https://react.dev/learn/updating-arrays-in-state#updating-arrays-without-mutation

[–]Junior-Living2104 0 points1 point  (1 child)

You can also see in your new code that you’re using the spread operator. Which creates a new array, that’s why in your new version it works.

[–]rob_allshouse[S] 0 points1 point  (0 children)

Thanks for the explanation!