您好,登錄后才能下訂單哦!
本篇內容介紹了“react中使用usestate踩坑如何解決”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
在react框架中,不適用類組件,使用函數式組件又想自定義數據維護業務開發的時候,就需要使用react提供的hook來完成。usestate就是最常見的一種hook。
const [name,setName] = useState('dx'); setName('dx1')
中括號實際是一個解構運算,第一個name是設置的值,第二個setName是只能用來改變name的方法。
因為useState不能像setState那樣進行合并更新,當使用useState第二個參數進行數據更新的時候,必須傳入一個完整的結構,而不僅僅只是改變的那一部分。
如果你想讓一個復雜的對象都能實現響應,可以分兩種情況。
第一種情況,這個復雜的對象每次都是整體發生改變,那么也可以直接使用useState。
第二種情況,你只是想讓許多的簡單數據都放到一個對象里面,這樣便于統一管理,那我建議,如果這些簡單數據之間都沒什么必然聯系的話,還是分開創建多個state更好。
在編碼的過程中,我們寧愿以空間復雜度換取時間復雜度,多創建幾個變量和創建一個變量,在用戶體驗上并不會有太多的差別。
但如果數據過于復雜,diff算法找到對應的變化及發生響應,大規模的重新渲染,這一過程,將會導致用戶體驗下降。
當使用usestate對數據進行更新,并不能立刻獲取到最新的數據。
const [name, setName] = useState('dx'); const handleTest = () => { console.log(name) // dx setName('dx1') console.log(name) // dx }
解決的辦法。
一、配合useEffect使用
const [name, setName] = useState('dx'); const handleTest = () => { console.log(name) //dx setName('dx1') console.log(name)//dx } useEffect(() => { console.log(name) //dx1 },[name])
二、創建一個新的變量保存最新的數據
const [name, setName] = useState('dx'); const handleTest = () => { console.log(name) //dx const newName = "dx1" setName(newName) console.log(newName) //dx1 }
三、用一個函數包裹,不推薦使用,因為函數里面所有的東西都會全部重新定義
const [name, setName] = useState('dx'); function text () { const handleTest = () => { console.log(name) //dx const newName = "dx1" setName(newName) console.log(name) //dx console.log(newName) //dx1 } useEffect(() => { console.log(name) //dx1 },[name]) return ( <div> {name} //點擊之前dx,點擊按鈕之后dx1 <button type="button" onClick={handleTest }>改變名字</button> </div> ) } console.log(name) //點擊按鈕之前dx,點擊按鈕之后dx1
強調,所有的hook和自定義hook都遵循此規則。
僅頂層調用 Hook :不能在循環,條件,嵌套函數等中調用useState()。
在多個useState()調用中,渲染之間的調用順序必須相同。
僅從React 函數調用 Hook:必須僅在函數組件或自定義鉤子內部調用useState()。
const [a, setA] = useState({c:1}) /** oldA為之前的a,return為設置的新值 */ setA((oldA) => { return {c: oldA.c + 1} })
const textObj = {name:'dx'} const [useState1, setUseState1] = useState(textObj ) const [useState2, setUseState2] = useState(textObj ) /** usestate的操作不要放在函數的最外層,這里只是簡單的代碼展示,你可以將set操作放在某個函數里面 */ setUseState1((oldUseState1) => { oldUseState1.age = 18 return {...oldUseState1} }) useEffect(() => { /** 改變一個會導致兩個都改變,深淺拷貝的問題 */ console.log(useState1) // {name: "dx", age: 18} console.log(useState2) // {name: "dx", age: 18} },[ useState1 ])
解決的方案
const textObj = {name:'dx'} const [useState1, setUseState1] = useState(textObj ) const [useState2, setUseState2] = useState(JSON.parse(JSON.stringify(textObj))) /** usestate的操作不要放在函數的最外層,這里只是簡單的代碼展示,你可以將set操作放在某個函數里面 */ setUseState1((oldUseState1) => { oldUseState1.age = 18 return {...oldUseState1} }) useEffect(() => { /** 改變一個會導致兩個都改變,深淺拷貝的問題 */ console.log(useState1) // {name: "dx", age: 18} console.log(useState2) // {name: "dx"} },[ useState1 ])
const textObj = {name:'dx'} const [useState1, setUseState1] = useState(textObj) /** usestate的操作不要放在函數的最外層,這里只是簡單的代碼展示,你可以將set操作放在某個函數里面 */ setUseState1((oldUseState1) => { oldUseState1.age = 18 return oldUseState1 useEffect(() => { console.log(useState1) },[ useState1 ]) //結果是沒有任何反應
解決方法
const textObj = {name:'dx'} const [useState1, setUseState1] = useState(textObj) /** usestate的操作不要放在函數的最外層,這里只是簡單的代碼展示,你可以將set操作放在某個函數里面 */ setUseState1((oldUseState1) => { oldUseState1.age = 18 /** 返回一個新的對象,useEffectc才能檢測得到 */ return {...oldUseState1} useEffect(() => { console.log(useState1) // {name: "dx", age: 18} },[ useState1 ])
你是否嘗試著將函數的引用作為一個變量保存到useState中去呢?
比如:
const testFunciton1 = () => { console.log({name: 'dx',age: '18'}) } /** usestate保存函數測試 */ const [stateFunction, setstateFunction] = useState<() => void>(testFunciton1); useEffect(() => { console.log(stateFunction) }, [stateFunction])
打印結果
代碼中從未調用過testFunciton1 ,結果testFunciton1卻被執行了
useEffect打印出來的卻是一個undefined。
稍微改動一下代碼,再測試
const testFunciton1 = () => { console.log({name: 'dx',age: '18'}) return { name: 'yx', age: '17' } } /** usestate保存函數測試 */ const [stateFunction, setstateFunction] = useState<() => void>(testFunciton1); useEffect(() => { console.log(stateFunction) }, [stateFunction])
結果
很明顯,在useState中,函數會自動調用,并且保存函數返回的值,而不能保存函數本身。
解決的方案
使用useState不能保存函數,那么可以使用useCallback這個hook。
/** useCallback,使用參數與useEffect一致 */ const testFunction = useCallback(() => { // useCallback返回的函數在useCallbak中構建 const testFunciton1 = () => { console.log({ name: 'dx', age: '18' }); return { name: 'yx', age: '17', }; }; return testFunciton1; }, []); useEffect(() => { console.log(testFunction()); }, [testFunction]);
結果
前一段時間面試某大廠的時候,講到了useState這個hook,要求簡單寫一下useState的實現原理,以下代碼只是一個粗淺的原理。
function useState(init) { let state; // useState無法保存函數 if(typeof init === 'function') { state = init() } else { state = init } const setState = (change) => { // 判斷一下是否傳遞過來的是函數 if(typeof change === 'function') { // 如果是函數,調用,并將之前的state傳過去,接收到的返回值作為新的state并賦值 state = change(state) } else { // 如果不是函數,直接賦值 state = change; } } return [state, setState] }
“react中使用usestate踩坑如何解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。