Overview
I’ve found that resetting indxg = -1 either before calling setColor(setcol) or after React re-renders keeps everything in sync, but resetting it between setColor(setcol) and the re-render breaks the hook order. I don’t yet understand why resetting before the state update works, yet doing so between the update and the render corrupts the behavior.
Unexpected Output:
After clicking “change color”, the console showed:
[‘blue’, ‘red’, ‘pink’, ‘red’] instead of [‘pink’,’red’]
Minimal Reproducible Example:
Corrupted code:
// Global state management
let m = [];
let indxg = -1;
function mystate(initial) {
indxg++;
const idx = indxg;
if (m[idx] === undefined) {
m[idx] = initial;
}
const setState = (newValue) => {
m[idx] = newValue;
};
return [m[idx], setState];
}
// Component Implementation (Broken)
function App() {
const [color1, setColor1] = mystate("blue");
const [color2, setColor2] = mystate("red");
const updateColor = () => {
setColor1("pink");
// PROBLEM: Reset AFTER state update indxg between setcol and render
indxg = -1;
root.render(<App />); // Re-render on update
};
return (
<>
<div style={{ background: color1 }}>Box 1</div>
<div style={{ background: color2 }}>Box 2</div>
<button onClick={updateColor}>Update</button>
</>
);
}
Working Solution:
// Global state management
let m = [];
let indxg = -1;
function mystate(initial) {
indxg++;
const idx = indxg;
if (m[idx] === undefined) {
m[idx] = initial;
}
const setState = (newValue) => {
m[idx] = newValue;
root.render(<App />); // Re-render on update
};
return [m[idx], setState];
}
function App() {
indxg = -1;
const [color1, setColor1] = mystate("blue");
const [color2, setColor2] = mystate("red");
const updateColor = () => {
setColor1("pink");
};
return (
<>
<div style={{ background: color1 }}>Box 1</div>
<div style={{ background: color2 }}>Box 2</div>
<button onClick={updateColor}>Update</button>
</>
);
}
Ai answer that i could not understand:
“The root cause is that your custom hook relies on a global indxg to assign each call a unique slot in the m array. React (and your stub) expects hooks to be called in the same order every render. If you reset indxg after calling setState (but before the next render), you shift your hook calls out of sync, so new slots get created and old ones are never reused—hence the extra entries. The fix is to reset indxg to -1 at the very start of your component render, so each call to mystate always increments from zero in the same sequence.“