Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@ryardley
Created October 31, 2018 01:59
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryardley/e83bad1985740ab33b18fc578ec1957a to your computer and use it in GitHub Desktop.
Save ryardley/e83bad1985740ab33b18fc578ec1957a to your computer and use it in GitHub Desktop.
let state = [];
let setters = [];
let firstRun = true;
let cursor = 0;
function createSetter(cursor) {
return function setterWithCursor(newVal) {
state[cursor] = newVal;
};
}
// This is the pseudocode for the useState helper
export function useState(initVal) {
if (firstRun) {
state.push(initVal);
setters.push(createSetter(cursor));
firstRun = false;
}
const setter = setters[cursor];
const value = state[cursor];
cursor++;
return [value, setter];
}
// Our component code that uses hooks
function RenderFunctionComponent() {
const [firstName, setFirstName] = useState("Rudi"); // cursor: 0
const [lastName, setLastName] = useState("Yardley"); // cursor: 1
return (
<div>
<Button onClick={() => setFirstName("Richard")}>Richard</Button>
<Button onClick={() => setFirstName("Fred")}>Fred</Button>
</div>
);
}
// This is sort of simulating Reacts rendering cycle
function MyComponent() {
cursor = 0; // resetting the cursor
return <RenderFunctionComponent />; // render
}
console.log(state); // Pre-render: []
MyComponent();
console.log(state); // First-render: ['Rudi', 'Yardley']
MyComponent();
console.log(state); // Subsequent-render: ['Rudi', 'Yardley']
// click the 'Fred' button
console.log(state); // After-click: ['Fred', 'Yardley']
@nnhjs
Copy link

nnhjs commented Sep 5, 2022

I think the variable firstRun's position is not right. The variable is not global variable, it should is a part of useState function.

prev...
useState(initVal) {
const firstRun = !state[cursor]
  if (firstRun) {
    state.push(initVal);
    setters.push(createSetter(cursor));
  }
after...

WDYT?

@Jeneko
Copy link

Jeneko commented Jan 7, 2024

I see the problem with the firstRun variable too.
The call of useState("Rudi") sets firstRun to false, so next call of useState("Yardley") won't push it's initialVal to the state:

if (firstRun) {
    state.push(initVal); // won't happen
...

I think it can be addressed by replacing the check of firstRun with the following check:

if (state.length <= cursor) {
    state.push(initVal);
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment