react中函數(shù)式組件React Hooks詳解
React Hooks
函數(shù)式組件
使用hooks理由
- 高階組件為了復(fù)用,導(dǎo)致代碼層級復(fù)雜
- 生命周期的復(fù)雜
- 寫成functional組件,無狀態(tài)組件,因?yàn)樾枰獱顟B(tài),又改成了class,成本高
在16.8版本之前函數(shù)式組件無法寫狀態(tài)所以一般只能用class組件成本比較高代碼嵌套比較深,并且鉤子函數(shù)(生命周期相對來說過于復(fù)雜)在16.8之后出了函數(shù)式組件的狀態(tài)后,很好的解決了這些弊端。
useState
在之前版本中函數(shù)式組件是不支持狀態(tài)的為了讓函數(shù)式組件更好的支持狀態(tài),可以利用useState
const [name,setName] = useState("Riven")主要利用這個(gè)useState的方法 也是一個(gè)數(shù)組它有個(gè)值一個(gè)是Riven,另一個(gè)是修改這個(gè)狀態(tài)的方法f()你可以打印一下自己查看console.log(useState(“Riven”)) 如上代碼就是將這個(gè)狀態(tài)和這個(gè)修改狀態(tài)的方法給解構(gòu)出來這樣就可以訪問到狀態(tài),并且進(jìn)行修改了
// rcc => react component class
// rfc => react component function
import React,{useState} from 'react'
//利用useState讓函數(shù)式組件支持狀態(tài)
function App(){
console.log(useState("Riven"));
//不支持狀態(tài)
const [name,setName] = useState("Riven")
const [age,setAge] = useState(25)
return(
<div>
app----{name}---{age}
<button onClick={()=>{
setName("kerwin")
setAge(100)
}}>click</button>
</div>
)
}
export default App
以上就是函數(shù)式組件的基本寫法了你肯定有許多問題?函數(shù)式組件的生命周期呢?函數(shù)式組件的傳值呢通信呢?沒有類組件的寫法這些應(yīng)該怎么寫呢?
請隨我繼續(xù)往后看
todolist小案例(函數(shù)式組件)
首先怎么獲取input框中的value值呢?
這里我們有兩種方法和類組件差不多
- 就是利用onChage事件
import React,{useState} from 'react'
function App(){
const [text, setText] = useState("")
return(
<div>
<input type="text" onChange={(ev)=>{
// console.log(ev.target)
setText(ev.target.value)
}} />
</div>
)
}
export default App
- 利用ref
這種方法較為復(fù)雜需要利用useRef
import React,{useState,useRef} from 'react'
const mytext = useRef(null)
<input type="text" onChange={(ev)=>{
// console.log(ev.target)
setText(ev.target.value)
}} ref={mytext} />
訪問的時(shí)候可以直接通過mytext.current.value得到value值
import React,{useState,useRef} from 'react'
function App(){
const [text, setText] = useState("")
const mytext = useRef(null)
return(
<div>
<input type="text" onChange={(ev)=>{
// console.log(ev.target)
setText(ev.target.value)
}} ref={mytext} />
<button onClick={()=>{
console.log(mytext.current.value)
}}>add</button>
</div>
)
}
export default App
完整的todolist
需要注意學(xué)習(xí)的地方
- input框value值獲取
- 怎么讓進(jìn)行添加
- 怎么讓添加完成后輸入框的value值清空
- 怎么進(jìn)行刪除
import React,{useState,useRef} from 'react'
function App(){
const [text, setText] = useState("")
const [list,setList] = useState(["111","222","333"])
const mytext = useRef(null)
//刪除函數(shù)只是想寫在外面
const handledelclick = (index)=>{
var newlist = [...list]
newlist.splice(index,1)
setList(newlist)
}
return(
<div>
<input type="text" onChange={(ev)=>{
// console.log(ev.target)
setText(ev.target.value)
}} ref={mytext} value={text} />
<button onClick={()=>{
// console.log(mytext.current.value) //ref
setList([...list,text]) //添加數(shù)組
setText(" ")
}}>add</button>
{
list.map((item,index)=>
<li key={item}>
{item}
<button onClick={()=>handledelclick(index)}>del</button>
</li>
)
}
</div>
)
}
export default App
useEffect
在函數(shù)式組件中我們沒有生命周期useEffect類似生命周期但不是生命周期
我們把數(shù)據(jù)請求放在函數(shù)組件的哪里呢?
- 首先需要知道useEffect接收兩個(gè)參數(shù),第一個(gè)是處理函數(shù),第二是依賴
- 第一個(gè)參數(shù)相當(dāng)于一旦創(chuàng)建就會(huì)執(zhí)行。
- 如果第二個(gè)參數(shù)傳入的依賴狀態(tài)改變也會(huì)自動(dòng)執(zhí)行
- 如果第二個(gè)參數(shù)傳入的依賴狀態(tài)為空就相當(dāng)于值會(huì)走一次
- 如果不傳任何狀態(tài)改變都會(huì)觸發(fā)第一個(gè)處理函數(shù)的執(zhí)行
- return 出來的這個(gè)函數(shù)只有銷毀的時(shí)候才會(huì)執(zhí)行
useEffect(()=>{
console.log("創(chuàng)建");
var id = setInterval(()=>{
console.log(111);
},2000)
return ()=>{
console.log("銷毀")
clearInterval(id)
}
},[])
下來看一個(gè)簡單的案例
import React,{useState,useEffect} from 'react'
const Child = ()=>{
useEffect(()=>{
console.log("創(chuàng)建");
var id = setInterval(()=>{
console.log(111);
},2000)
return ()=>{
console.log("銷毀")
clearInterval(id)
}
},[])
return(
<div>
Child
</div>
)
}
const App = ()=>{
//useEffect(處理函數(shù),[依賴])
const [text, setText] = useState("1111")
const [age, setAge] = useState(25)
// useEffect(()=>{
// console.log("創(chuàng)建或者更新的時(shí)候執(zhí)行")
// },[text])
//傳入空數(shù)組相當(dāng)于cdm
//[text] 只有text的改變才會(huì)執(zhí)行一次
//第二參數(shù)不傳表示任何狀態(tài)改變都會(huì)重新執(zhí)行
return(
<div>
App ----{text}
<button onClick={()=>{
setText("22222")
}}>click-text</button>
<br/>
{age}
<button onClick={()=>{
setAge(100)
}}>click-age</button>
{
age===25?
<Child/>:
null
}
</div>
)
}
export default App
在實(shí)際應(yīng)用中函數(shù)式組件會(huì)自動(dòng)傳一個(gè)參數(shù)props 這樣我們就可以訪問到props里面的屬性了
props.match.params.myid props.history.goBack()
import React,{useState,useEffect} from 'react'
import { PageHeader} from 'antd';
import axios from 'axios'
const Preview = (props)=>{
const [title, settitle] = useState("")
const [content, setcontent] = useState("")
const [category, setcategory] = useState([])
useEffect(()=>{
axios.get(`http://localhost:8000/articles/${props.match.params.myid}`).then(res=>{
console.log(res.data)
let {title,content,category} = res.data
settitle(title)
setcontent(content)
setcategory(category)
})
},[props])
return (
<div>
<PageHeader
className="site-page-header"
onBack={() => {
// console.log("back",this.props.history)
props.history.goBack()//返回上一個(gè)頁面
}} //返回按鈕
title={title}
subTitle={category.join("/")}
/>
<div style={{ padding: "24px" }} dangerouslySetInnerHTML={{
__html:content
}}></div>
</div>
)
}
export default Preview
useCallback
防止因?yàn)榻M件重新渲染,導(dǎo)致方法被重新創(chuàng)建 ,起到緩存作用; 只有第二個(gè)參數(shù) 變化了,才重新聲明一次
也就是只需要當(dāng)需要某個(gè)狀態(tài)改變的時(shí)候才讓函數(shù)執(zhí)行一次
import React,{useState,useCallback} from 'react'
export default function App() {
const [text,settext] = useState("1111")
const test = useCallback(
() => {
console.log(text)
},
[text],
)
test()
return (
<div>
App-{text}
<button onClick={()=>{
settext("22222")
}}>click</button>
</div>
)
}
useContext useReducer
首先這兩個(gè)都是用來在函數(shù)式組件中進(jìn)行非父子通信的
首先需要?jiǎng)?chuàng)建一個(gè)GlobalContext 用來包裹這些生產(chǎn)者的
import React from 'react' const GlobalContext = React.createContext() export default GlobalContext
然后引入
import GlobalContext from './store'
總體代碼如下
import React,{useReducer,useContext} from 'react'
import GlobalContext from './store'
import reducer from './store/reducer'
import axios from 'axios'
const Child1 = ()=>{
// useContext(GlobalContext)
// console.log(useContext(GlobalContext))
let {state,dispatch} = useContext(GlobalContext)
return (
<div>
child1-----{state.text}
<button onClick={()=>{
dispatch({
type:"Change_text",
payload:"child11111111111"
})
}}>click</button>
</div>
)
}
const Child2 = ()=>{
let {state,dispatch} = useContext(GlobalContext)
return (
<div>
Child2----{state.text}
<button onClick={()=>{
axios.get("http://localhost:8000/rights").then(res=>{
// console.log(res.data)
dispatch({
type:"Change_list",
payload:res.data
})
})
}}>異步數(shù)據(jù)</button>
{
state.list.map(item=>
<li key={item.id}>{item.title}</li>
)
}
</div>
)
}
const App = ()=>{
const [state,dispatch] = useReducer(reducer,{
isShow:true,
list:[],
text:"我是公共的狀態(tài)"
}) //[公共的狀態(tài),改變公共狀態(tài)的方法]
return (
<GlobalContext.Provider value={{
state,
dispatch
}}>
<Child1/>
<Child2/>
</GlobalContext.Provider>
)
}
export default App這里需要注意
const [state,dispatch] = useReducer(reducer,{
isShow:true,
list:[],
text:"我是公共的狀態(tài)"
}) //[公共的狀態(tài),改變公共狀態(tài)的方法]
這塊useReducer(reducer) 其實(shí)相當(dāng)于一個(gè)數(shù)組里面有兩個(gè)值一個(gè)是公共的狀態(tài)另外一個(gè)改變公共狀態(tài)的方法
訪問的時(shí)候可以通過usecontext(GlobalContext) 里面有兩個(gè)值一個(gè)為state,一個(gè)為dispatch
const Child1 = ()=>{
// useContext(GlobalContext)
// console.log(useContext(GlobalContext))
let {state,dispatch} = useContext(GlobalContext)
return (
<div>
child1-----{state.text}
<button onClick={()=>{
dispatch({
type:"Change_text",
payload:"child11111111111"
})
}}>click</button>
</div>
)
}異步也差不多
const Child2 = ()=>{
let {state,dispatch} = useContext(GlobalContext)
return (
<div>
Child2----{state.text}
<button onClick={()=>{
axios.get("http://localhost:8000/rights").then(res=>{
// console.log(res.data)
dispatch({
type:"Change_list",
payload:res.data
})
})
}}>異步數(shù)據(jù)</button>
{
state.list.map(item=>
<li key={item.id}>{item.title}</li>
)
}
</div>
)
}
reducer文件
const reducer = (prevstate,action)=>{
let {type,payload} = action
switch(type){
case "Change_text":
//深復(fù)制老狀態(tài),返回新狀態(tài)
// prevstate.text
// var newstate = {...prevstate}
return {
...prevstate,
text:payload
} // immutable
case "Change_list":
return {
...prevstate,
list:payload
}
default:
return prevstate
}
}
export default reducer函數(shù)式組件的父子通信問題
這個(gè)和類組件差不多,只不過是函數(shù)式組件會(huì)自動(dòng)傳一個(gè)參數(shù)props這樣就可以直接訪問到props里面的屬性了
- 父傳子(屬性)
- 子傳父(回調(diào)函數(shù))
// 父子通信 ,靠屬性
// 父->子 , 屬性
// 子->父 , callback( 屬性傳過去一個(gè)回調(diào)函數(shù))
import React,{useState} from 'react'
const Navbar = (props)=>{
console.log(props)
return <div>
navbar-{props.myname}
<button onClick={()=>{
props.onEvent()
}}>click</button>
</div>
}
const Sidebar = ()=>{
return <div>
Sidebar
<ul>
<li>111111</li>
<li>222222</li>
<li>333333</li>
</ul>
</div>
}
const Child = (props)=>{
return <div>
child --{props.children}
</div>
}
export default function App() {
const [show, setshow] = useState(false)
return (
<div>
<Navbar myname="測試的抽屜" onEvent={()=>{
console.log("父組件中調(diào)用")
setshow(!show)
}}/>
{
show?
<Sidebar/>
:null
}
<Child>
<div>child-11111111</div>
<div>child-22222222</div>
</Child>
</div>
)
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- React Hooks 鉤子的具體使用
- 使用React Hooks模擬類組件的生命周期方法
- React使用Hooks從服務(wù)端獲取數(shù)據(jù)的完整指南
- React中不適當(dāng)?shù)腍ooks使用問題及解決方案
- React?中hooks之?React.memo?和?useMemo用法示例總結(jié)
- react hooks實(shí)現(xiàn)防抖節(jié)流的方法小結(jié)
- React?Hooks的useState、useRef使用小結(jié)
- react中hooks使用useState的更新不觸發(fā)dom更新問題及解決
- react16中的hooks的底層實(shí)現(xiàn)原理
相關(guān)文章
React實(shí)現(xiàn)多個(gè)場景下鼠標(biāo)跟隨提示框詳解
這篇文章主要為大家介紹了React實(shí)現(xiàn)多個(gè)場景下鼠標(biāo)跟隨提示框詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
React避坑指南之useEffect 依賴引用類型問題分析
這篇文章主要介紹了React避坑指南之useEffect 依賴引用類型問題分析,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
react使用useState修改對象或者數(shù)組的值無法改變視圖的問題
這篇文章主要介紹了react使用useState修改對象或者數(shù)組的值無法改變視圖的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
React組件如何優(yōu)雅地處理異步數(shù)據(jù)詳解
這篇文章主要為大家介紹了React組件如何優(yōu)雅地處理異步數(shù)據(jù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
React18的useEffect執(zhí)行兩次如何應(yīng)對
這篇文章主要給大家介紹了關(guān)于React18的useEffect執(zhí)行兩次如何應(yīng)對的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用React具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
封裝一個(gè)最簡單ErrorBoundary組件處理react異常
這篇文章主要介紹了一個(gè)處理react異常的ErrorBoundary組件,簡單實(shí)用,代碼詳細(xì),對這個(gè)組件感興趣的朋友可以參考下2021-04-04
react如何實(shí)現(xiàn)側(cè)邊欄聯(lián)動(dòng)頭部導(dǎo)航欄效果
這篇文章主要介紹了react如何實(shí)現(xiàn)側(cè)邊欄聯(lián)動(dòng)頭部導(dǎo)航欄效果,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03

