Explaining unsafe React's setState

by Onilton Maciel

HTML

<script src="https://cdn.jsdelivr.net/gh/eu81273/jsfiddle-console/console.js"></script>

JavaScript

// imagine props and state is the same 
// as this.props and this.state
var props = { }
var state = { counter: 0 }

/* Our fake implementation of react setState */
var setStatesToRun = []
function setState(myFunction){
	setStatesToRun.push(myFunction);
}

/* Our fake implementation of react batch update */
function batchRunStateUpdates() {
  propsLocal = props
  stateLocal = state

  f1 = setStatesToRun.shift() // get setState to run
  newState = f1(stateLocal, propsLocal) 
  console.log("Local state")
  console.log(newState) // newState: { counter: 3 }
  console.log("Global state")
  console.log(state) // state: { counter: 0 }

  f2 = setStatesToRun.shift()
  newState = f2(newState, propsLocal)
  console.log("Local state")
  console.log(newState) // newState: { counter: 2 }
  console.log("Global state")
  console.log(state) // state: { counter: 0 }

  // ... get the next setState function
  // This whole block should be a loop, but it is this way 
  // to make the example easier to understand

  console.log("Will update global state")
  state = newState  
  console.log("Global State")
  console.log(state) // state: { counter: 2 } // WRONG!!
}

console.log("setStatesToRun")
console.log(setStatesToRun)


// Right
setState((prevState, props) => {
   console.log("Will run increment by 3")
  return {
    counter: prevState.counter + 3
  }
}); 

// Wrong, we will use the state
setState((prevState, props) => { 
	console.log("Will run increment by 2"); 
	return {
  	counter: state.counter + 2 
    // replace with prevState.counter + 2 to make it work
	}
});


console.log("setStatesToRun")
console.log(setStatesToRun)


batchRunStateUpdates();