建設(shè)部門網(wǎng)站查詢湖南百度推廣代理商
React Hooks 常見錯誤
前言
本片文章主要是在寫react hooks的時候,遇到的常見錯誤的寫法,和錯誤。也是一個對只是的鞏固和總結(jié)。
錯誤一
上代碼:正確寫法
function TestReactHooksError() {const [test, setTest] = useState('test');useEffect(() => {if(test) {console.log(test)}}, [test]);return (<div><button onClick={()=>setTest(test + 1)}>{test}click</button></div>);
}
export default TestReactHooksError
解析:
功能,點擊按鈕,按鈕文案改動,并且控制臺打印文案結(jié)果。
稍作改動:
function TestReactHooksError() {const [test, setTest] = useState('test');if (test) {useEffect(() => {console.log(test)}, [test]);}return (<div><button onClick={() => setTest(test + 1)}>{test}click</button></div>);
}
export default TestReactHooksError
可以看到報錯了:
搜狗翻譯:
React鉤子“useEffect”被有條件地調(diào)用。React掛鉤必須在每個組件渲染中以完全相同的順序調(diào)用
正常翻譯:
就是鉤子函數(shù)必須按順序執(zhí)行,因為底層是按順序執(zhí)行的,所以如果加入判斷的話,可能有不可預(yù)知的錯誤。
錯誤二
上代碼:正確寫法
function TestReactHooksError() {const [test, setTest] = useState([1, 2, 3, 4, 5]);useEffect(() => {consoleLog()}, []);const consoleLog = (value) => {for (let i = 0, len = test.length; i < len; i++) {console.log(test[i])}}return (<div>{test.map((item) => {return <span key={item}>{item}</span>})}</div>);
}
export default TestReactHooksError
解析:
功能,渲染列表,并且控制臺打印結(jié)果。
稍作改動:
function TestReactHooksError() {const [test, setTest] = useState([1,2,3,4,5]);for (let i=0, len = test.length; i < len; i++) {useEffect(() => {console.log(test[i])}, [test[i]]);}return (<div>{test.map((item)=>{return <span key={item}>{item}</span>})}</div>);
}
export default TestReactHooksError
報錯:
可以看到結(jié)果都正常打印了,但是報錯了。
搜狗翻譯:
React掛鉤“useEffect”可以執(zhí)行多次??赡苁且驗樗窃谘h(huán)中調(diào)用的。React掛鉤必須在每個組件渲染中以完全相同的順序調(diào)用
正常翻譯:
不能在循環(huán)中使用hooks,因為還是可能會導(dǎo)致執(zhí)行順序錯誤,導(dǎo)致結(jié)果錯誤。
錯誤三
上代碼: 正確寫法
function TestReactHooksError() {const [testState, setTestState] = useState('testState')const clickState = () => {console.log(testState)}return (<div><button onClick={()=>clickState()}>click</button></div>);
}
export default TestReactHooksError
解析:
功能,點擊按鈕控制臺打印結(jié)果。
稍作改動:
function TestReactHooksError() {const clickState = () => {const [testState, setTestState] = useState('testState')console.log(testState)}return (<div><button onClick={()=>clickState()}>click</button></div>);
}
export default TestReactHooksError
報錯:
搜狗翻譯:
React掛鉤“useState”在函數(shù)“clickState”中調(diào)用,該函數(shù)既不是React函數(shù)組件,也不是自定義React掛鉤函數(shù)。React組件名稱必須以大寫字母開頭。React掛鉤名稱必須以單詞“use”開頭
正常翻譯:
這個翻譯的很明白,就是不能在普通函數(shù)中使用,因為react不會理解它是一個組件或者是自定義hooks。
錯誤四
上代碼: 錯誤寫法
class MyComponent extends React.Component {constructor(props) {super(props);this.state = {testState: 'testState',};}useEffect(() => {console.log(this.state.testState)}, [this.state.testState]);render() {return (<div><p>You clicked {this.state.testState} times</p><button onClick={() => this.setState({ testState: this.state.testState + 1 })}>Click</button></div>);}
}
報錯:
報錯語法格式錯誤。所以不能混合使用
錯誤五
正確的寫法:
function TestReactHooksError() {const [testState, setTestState] = useState('testState')function clickState() {console.log(testState)}return (<div><button onClick={() => setTestState(testState + 1)}>{testState}</button><button onClick={() => clickState()}>click</button></div>);
}
export default TestReactHooksError
稍作修改:
function TestReactHooksError() {const [testState, setTestState] = useState('testState')function clickState() {console.log(testState)}return (<div><button onClick={() => setTestState(testState + 1)}>{testState}</button><button onClick={clickState}>click</button></div>);
}
export default TestReactHooksError
在 JSX 的事件處理程序中調(diào)用函數(shù)時,應(yīng)該傳遞函數(shù)本身而不是函數(shù)的返回值。改為 onClick={() => handleClick()} 或者將 handleClick 函數(shù)定義在組件外部并將其作為 prop 傳遞給組件。由于當(dāng)前的寫法每次渲染都會創(chuàng)建一個新的函數(shù)和事件處理程序,因此會導(dǎo)致浪費和性能問題。
注意:
當(dāng)然在最新的版本中不會有這個問題因為,React 已經(jīng)對函數(shù)事件處理程序進行了自動綁定,所以在最新版本中不會出現(xiàn)這個問題。這是因為最新版本的 React 使用了異步渲染機制,將多次渲染時創(chuàng)建的函數(shù)緩存起來進行重用,從而避免了性能問題。
錯誤六
使用useEffect時沒有傳入依賴項,這可能會導(dǎo)致無限制地執(zhí)行useEffect,當(dāng)然如果你就是為了重復(fù)執(zhí)行可以跳過這個。
正確寫法:
function TestReactHooksError() {const [test, setTest] = useState('test');useEffect(() => {console.log(test)}, [test]);return (<div><button onClick={()=>setTest(test + 1)}>{test}click</button></div>);
}
export default TestReactHooksError
稍作修改:
function TestReactHooksError() {const [test, setTest] = useState('test');useEffect(() => {console.log(test)});return (<div><button onClick={()=>setTest(test + 1)}>{test}click</button></div>);
}
export default TestReactHooksError
修改之后,如果之后再加入其他按鈕渲染數(shù)據(jù),當(dāng)其他數(shù)據(jù)變化時,還是會執(zhí)行useEffect,所以需要正確的添加,依賴項。
錯誤七
定時器
上代碼:正確的寫法
分別使用setTimeout和setInterval
function TestReactHooksError() {const [timer, setTimer] = useState(0);const [timerS, setTimerS] = useState(0);useEffect(() => {setTimeout(() => {setTimer(timer + 1)}, 1000)}, [timer]);useEffect(() => {setInterval(() => {setTimerS(timerS => timerS + 1)}, 1000)}, []);return (<div>{timer}-{timerS}</div>);
}
export default TestReactHooksError
但是這樣寫有一個問題,如果仔細(xì)看頁面計時顯示會發(fā)現(xiàn)兩個時間有偏差。setTimeout會慢一些,但是這也不難分析,因為setTimeout 和 setInterval 的執(zhí)行方式是不同的。setTimeout 在每次計時器更新時都會重新創(chuàng)建一個新的計時器,而 setInterval 只會在組件掛載時創(chuàng)建一個計時器。因此,setInterval 的計時器會一直運行,而 setTimeout 的計時器則會受到上一個計時器執(zhí)行時間的影響,可能會出現(xiàn)延遲。另外,由于 setTimeout 是在依賴數(shù)組中的 timer 更新時執(zhí)行的,當(dāng) timer 發(fā)生變化時,會重新創(chuàng)建一個新的計時器,這可能會導(dǎo)致計時器的執(zhí)行時間出現(xiàn)偏差。
說簡單點就是,setInterval 每次只是在設(shè)定的時間后馬上執(zhí)行,而setTimeout需要依賴數(shù)據(jù)變化并且每次都重新創(chuàng)建,所以會慢一些
稍作修改
錯誤的寫法:
useEffect(() => {setInterval(() => {setTimerS(timerS + 1)console.log(timerS)}, 1000)
}, [timerS]);
可以看到頁面顯示抽搐的時間
總結(jié)
先這么多文章還會更新。。。
如有問題歡迎指出,感謝