1. About useState
- What does useState do to get an array that can both read and write?
- What happens when setN is executed? Does n change? Will App() be re-executed?
- If App() is reexecuted, will the value of useState(0) be different each time?
function App() {
const [n, setN] = useState(0);
const [m, setM] = useState(0);
return (
<div className="App">
<p>{n}</p>
<p>
<button onClick={() => setN(n + 1)}>+1</button>
</p>
<p>{m}</p>
<p>
<button onClick={() => setM(m + 1)}>+1</button>
</p>
</div>
);
}
Copy the code
Analysis:
- setN
- SetN must modify some data x, putting n+1 into that x
- SetN must trigger rerendering
- useState
- UseState will definitely read the latest value of n from x
- x
- Each component has its own data x, which we’ll name state
2. Write useMyState as a simple alternative to useState
import React from "react";
import ReactDOM from "react-dom";
const rootElement = document.getElementById("root");
let _state;
const myUseState = (initState) => {
_state = ( _state === undefined ? initState : _state);
const setState = (newState) => {
_state = newState
render()
}
return [_state,setState]
}
const render = () => ReactDOM.render(<App />, rootElement);
function App() {
const [n, setN] = myUseState(0);
return (
<div className="App">
<p>{n}</p>
<p>
<button onClick={() => setN(n + 1)}>+1</button>
</p>
</div>
);
}
ReactDOM.render(<App />, rootElement);
Copy the code
- But such code also runs into problems. What if there is an M in addition to n?
3. Advanced version of useMyState method
import React from "react";
import ReactDOM from "react-dom";
const rootElement = document.getElementById("root");
let _state = [];
let index = 0;
const myUseState = (initState) => {
let currentIndex = index;
_state[currentIndex] = ( _state[currentIndex] === undefined ? initState : _state[currentIndex]);
const setState = (newState) => {
_state[currentIndex] = newState
index = 0
render()
}
index += 1
return [_state[currentIndex],setState]
}
const render = () => ReactDOM.render(<App />, rootElement);
function App() {
const [n, setN] = myUseState(0);
const [m, setM] = myUseState(0);
return (
<div className="App">
<p>{n}</p>
<p>
<button onClick={() => setN(n + 1)}>+1</button>
</p>
<p>{m}</p>
<p>
<button onClick={() => setM(m + 1)}>+1</button>
</p>
</div>
);
}
Copy the code
- Disadvantages of using the array method:
- The order in which useState is called is very important
- First render n on the first, M on the second, k on the third
- The order of calls for the second rendering must be exactly the same
- React does not allow if… else..
- Example:
const [n, setN] = React.useState(0);
let m, setM;
if (n % 2 === 1) {
[m, setM] = React.useState(0);
}
Copy the code
4. N
function App() {
const [n, setN] = React.useState(0);
const log() = = >setTimeout(() => console.log(`n: ${n}`), 3000);
return (
<div className="App">
<p>{n}</p>
<p>
<button onClick={() => setN(n + 1)}>+1</button>
<button onClick={log} >log</button> </p> </div> ); } // First click +1, then clicklog.logIs 1 // First clicklog, plus 1,logA value of 0Copy the code
- Because every time useState renders the n in App(), it is a new N, that is, n=0 and n=1 coexist. After clicking log, the log produces the original n equal to 0, instead of the new N generated after +1.
5, useRef
function App() { const nRef = React.useRef(0); //nRef is an object {current:0} constlog() = = >setTimeout(() => console.log(`n: ${nRef.current}`), 1000);
return (
<div className="App">
<p>{nRef.current}</p>
<p>
<button onClick={() => (nRef.current += 1)}>+1</button>
<button onClick={log} >log</button>
</p>
</div>
);
}
Copy the code
- This solves the n clone problem, but there’s a new problem: the UI doesn’t update in real time, meaning useRef doesn’t trigger rendering
- Solution: Add using useState to trigger updates (not recommended)
- Example:
const nRef = React.useRef(0);
const update = React.useState()[1];
const log() = = >setTimeout(() => console.log(`n: ${nRef.current}`), 1000);
return (
<div className="App"> < p > {nRef. Current} here and cannot be updated in real time < / p > < p > < button onClick = {() = > ((nRef. Current + = 1), update(nRef.current))}> +1 </button> <button onClick={log} >log</button>
</p>
</div>
);
Copy the code
6, summary
-
Each function component corresponds to a React node
-
Each node holds state and index
-
UseState reads state[index]
-
Index is determined by the order in which useState appears
-
SetState modifies state and triggers an update
-
Each time you render, the component function is executed again
-
All corresponding states have a doppelganger.
-
If you don’t want to have such a “split body” situation
-
You can use useRef/useContext, etc