react hook?官網地址:https://react.docschina.org/docs/hooks-intro.html
函數式組件:
const? App=()=>{? ?renturn (? ?<div><div/>)? }??
函數式組件特點:1.沒有state放數據? 2.沒有生命周期 3.沒有this指向問題
hook主要是服務于函數是組件的,常用的hook有:
1.useState
import?{?useState?}?from?'react'
function?App1()?{
????//?const?[變量名,?修改變量的方法]?=?useState(變量的初始值)
????const?[num,?setNum]?=?useState(0)
????function?btnClick(){
????????//?setNum的作用是將最新的一個值賦值給num
????????setNum(num+1)
????}
????return?(
????????<div>
????????????<h1>{num}</h1>
????????????<button?onClick={btnClick}>累加</button>
????????</div>
????)
}
export?default?App1;
2.useEffect(相當于三個生命周期 componentDidMount?+?componentDidUpdate?+?componentWillUnmount useEffect可以檢測數據更新 )
useEffect(callback,Array)有兩個參數? 如果Array的[]代表不檢測任何數據
?/useEffect包含了三個聲明周期??其中一個是銷毀的生命周期??第二參數不寫的時候只檢測return里面銷毀的的數據?如果寫第二個參就不要寫return? ? ?import?{? useEffect?}?from?'react'
? (函數式組件中寫下面這一段)
? ?useEffect(()?=>?{
????????console.log('數據更新了');
????????return?()?=>?{
????????????console.log('組件銷毀了');
????????}
????},?[])
3.useContext 和createContext(使用上下文和創建上下文)
import?React?from?'react'
//?引入這三個hook
import?{?useState,?createContext,?useContext?}?from?'react'
//創建上下文
const?NumContext?=?createContext()
//?創建子組件
function?Child()?{
????//?使用上下文
????const?num?=?useContext(NumContext)
????//?console.log(useContext(NumContext));
????return?<h1>{num}</h1>
}
export?default?function?App1()?{
????const?[num,?setNum]?=?useState(100)
????return?(
????????<div>
????????????<NumContext.Provider?value={num}>
????????????????<Child?/>
????????????</NumContext.Provider>
????????????<button?onClick={()?=>?setNum(num?+?1)}>累加</button>
????????</div>
????)
}//全局創建上下文(const?NumContext?=?createContext()) ==>全局上下文父組件中包裹子組件(???<NumContext.Provider?value={num}>? ? ?<Child?/>??</NumContext.Provider> 提供器傳遞參數必須是value)==>子組件使用上下文(??const?num?=?useContext(NumContext)? 標簽內使用?<h1>{num}</h1>)
3.1createContext(使用上下文和創建上下文)
import?React?from?'react'
import?{?useState,?createContext?}?from?'react'
const?NumContext?=?createContext()
function?Child()?{
????return?(
????????<NumContext.Consumer>
????????????{
????????????????num?=>?<h1>{num}</h1>
????????????}
????????</NumContext.Consumer>
????)
}
function?App2()?{
????const?[num,?setNum]?=?useState(0)
????return?(
????????<div>
????????????{/*?相當于react-redux里面的提供器?*/}
????????????<NumContext.Provider?value={num}>
????????????????<Child?/>
????????????</NumContext.Provider>
????????????<button?onClick={()?=>?setNum(num?+?1)}>累加</button>
????????</div>
????)
}//提供器傳遞參數(Provider?)===>消費器使用(Consumer? 函數的形式使用)
export?default?App2
4.useReducer(useReducer結合usecontext實現redux)
import?React?from?'react'
//?引入這三個hook
import?{?createContext,?useContext,?useReducer?}?from?'react'
//創建上下文
const?NumContext?=?createContext()
//?創建子組件
function?Child()?{
????//?使用上下文
????const?{?state?}?=?useContext(NumContext)
????//?console.log(useContext(NumContext));
????return?<h1>{state.num}</h1>
????//?{state.data.name}
}
//?創建組件
function?Dispatch()?{
????const?{?dispatch?}?=?useContext(NumContext)
????return?(
????????<button?onClick={()?=>?dispatch({?type:?'addFn',?value:?10 })}>累加</button>
????)
}
function?numReducer(state,?action)?{
????let?newState?=?JSON.parse(JSON.stringify(state))
????switch?(action.type)?{
????????case?"addFn":
????????????newState.num?+=?action.value
????????????break;
????????default:
????????????break;
????}
????return?newState
}
export?default?function?App1()?{
????//?從useReducer這個hook結構出這兩個對象useReducer(第一個參數是函數,第二個參數是傳遞初始的值或者信息)
????const?[state,?dispatch]?=?useReducer(numReducer,?{?num:?0,?data:?{?name:?'你好世界'?}?})
????//?console.log(useReducer(numReducer,?{?num:?0?}));
????return?(
????????<div>
????????????{/*?//?Provider的value屬性,有兩種傳遞參數的形式,第一種是直接傳值,第二種是以對象的形式傳值?*/}
????????????<NumContext.Provider?value={{?state,?dispatch?}}>
????????????????<Child?/>
????????????????<Dispatch?/>
????????????</NumContext.Provider>
????????</div>
????)
}
5.useRef
import?React?from?'react'
import?{?useRef?}?from?'react'
export?default?function?App4()?{
????//?一開始給null的原因是不知道把ref給那個元素
????const?element?=?useRef(null)
????return?(
????????<div>
????????????{/*?沒有input的value值沒有放在state里面的是不受控組件?*/}
????????????<input?type="text"?ref={element}?/>
????????????<button?onClick={()?=>?console.log(element.current.value)}>按鈕</button>
????????</div?>
????)
}
Fragment和空標簽(react中按需引入)
<ul>
????????????????????{
????????????????????????//?eslint-disable-next-line
????????????????????????this.state.arr.map((item,?index)?=>?{
????????????????????????????return?<Fragment?key={index}>
????????????????????????????????<h1>{item}</h1>
????????????????????????????</Fragment>
????????????????????????})
????????????????????}
? ? ? ? </ul>
//?Fragment這個hook作用主要是當你想要循環的時候比如又不想要li標簽?但是循環又需要key屬性的時候可以只用Fragment?但是只能是key?放類名之類的是無效且會報錯 空標簽無法寫屬性
錯誤邊界
PureComponent(能夠監聽子組件和父組件里面的props和state的變化 相當于生命周期內判斷和上一個是否相等不相等就返回false相等就返回true不往下執行)
高階組件HOC:本質是函數(高階組件就是函數里面返回組件)
import?React,?{?Component?}?from?'react'
//?創建兩個低階的組件
class?Sub1?extends?Component?{
????render()?{
????????return?(
????????????<h1>{this.props.num}</h1>
????????)
????}
}
class?Sub2?extends?Component?{
????//?state?=?{
????//?????num:?1
????//?}
????render()?{
????????return?(
????????????<h1>{this.props.num}</h1>
????????)
????}
????//?componentDidMount()?{
????//?????setTimeout(()?=>?{
????//?????????this.setState({
????//?????????????num:?4
????//?????????})
????//?????},?4000)
????//?}
}
//?高階組件HOC本質是一個函數???高階組價就是函數里返回組件
//?高階函數是函數里面返回函數
const?HocFn?=?(Comp,?timeout,?mynum)?=>?{
????return?(
????????//?高階函數里面規定函數名可以不寫
????????class?extends?Component?{
????????????state?=?{
????????????????num:?1
????????????}
????????????render()?{
????????????????return?(
????????????????????<Comp?num={this.state.num}?/>
????????????????)
????????????}
????????????componentDidMount()?{
????????????????setTimeout(()?=>?{
????????????????????this.setState({
????????????????????????num:?mynum
????????????????????})
????????????????},?timeout)
????????????}
????????}
????)
}
const?Sub1Fn?=?HocFn(Sub1,?2000,?100)
const?Sub2Fn?=?HocFn(Sub2,?2000,?200)
export?default?function?App7()?{
????return?(
????????<div>
????????????<Sub1Fn></Sub1Fn>
????????????<hr?/>
????????????<Sub2Fn></Sub2Fn>
????????</div>
????)
}
高階函數HOF:本質是函數(高階組件就是函數里面返回函數)
懶加載loadlazy和suspense一起使用
1.創建一個子組件和一個父組件
2.父組件中constSub=React.lazy(()=>import('.子組件路徑'));
3.react中引入suspense
4.父組件中<Suspense fallback={<div>loading...</div>}> <子組件/> </Suspense>