react學習筆記(四) --- 自定義hook與高階組件的寫法


1、自定義hook

當我們想在兩個函數之間共享邏輯時, 我們會把它提取到第三個函數中,而組件和Hook都是函數,所以也同樣適用這種方式

自定義hook是一個函數, 其名稱是以use開頭, 函數內部可以調用其他的hook

import React, {useEffect, useState} from 'react';
import ReactDom from 'react-dom' const useTimer = () => {  //注意:這里的函數是需要以use開頭 let [count, setCount] = useState(0) useEffect(() => {   //相當於componentDidMount let timer = setInterval(() => { setCount(count => ++ count) }, 1000) return () => {  //相當於componentWillUnmount clearInterval(timer) } }, []) return count }

const CounterOne = () => {
    // let [count, setCount] = useState(0)
    //
    // useEffect(() => {
    //     let timer = setInterval(() => {
    //         setCount(count => ++ count)
    //     }, 1000)
    //     return () => {
    //         clearInterval(timer)
    //     }
    // }, [])
    let count = useTimer()
    return <h2>CounterOne ---{count}</h2>
}

const CounterTwo = () => {
    // let [count, setCount] = useState(0)
    //
    // useEffect(() => {
    //     let timer = setInterval(() => {
    //         setCount(count => ++ count)
    //     }, 1000)
    //     return () => {
    //         clearInterval(timer)
    //     }
    // }, [])
    let count = useTimer()
    return <h3>CounterTwo ---{count}</h3>
}

const App = () => {
    return <div>
        <CounterOne/>
        <CounterTwo/>
    </div>
}

ReactDom.render(<App/>, window.root)

原本useEffect與useState是不能放在函數里,如果放在use開頭的函數里,系統會認為是自定義的hook,這樣就可以對對應的方法進行封裝和使用

 案例2: 對dispatch進行擴充,實現改變前與改變后值的打印

import React, {useEffect, useReducer} from 'react';
import ReactDom from 'react-dom'

const useLogger = () => {
    const reducer = (state, config) => {
        if(config.type === 'count') {
            return {
                ...state,
                count: state.count + config.step
            }
        } else if(config.type === 'name') {
            return {
                ...state,
                name: config.target
            }
        }
    }
    let [state, dispatch] = useReducer(reducer, {name: 'yfbill', count: 0})
 const actions = (config) => { //對原有dispatch進行擴充 console.log('before', state) dispatch(config) } useEffect(() => { console.log('after', state) }) return [state, actions] //輸出的擴充后的dispatch

}

const Item = () => {
    let [state, actions] = useLogger()
    return <div>
        <h3>this is Item---name: {state.name} --- count: {state.count}</h3>
        <button onClick={() => { actions({type: 'count', step: 1})}}>count++</button>
        <button onClick={() => { actions({type: 'name', target: 'aaaa'})}}>changeName</button>
    </div>
}

const App = () => {
    return <div>
        <h2>this is App</h2>
        <Item/>
    </div>
}

ReactDom.render(<App/>, window.root)

注意:以上這個嵌入式的寫法可以用作數據的請求,方便封裝操作 

 2、高階組件的寫法

import React from 'react';
import ReactDom from 'react-dom'

const App = props => {
    console.log(props)
    return <div>this is App</div>
}

//扁平化的高階組件(推薦使用) // const Wrap = (config = {}, Comp) => { // return props => { // return <Comp {...config} {...props}/> // }
// }

//第二種方式的高階組件
const Wrap = (config = {}) => {
    return Comp => {
        return props => {
            return <Comp {...config} {...props}/>
        }
    }
}

// let Instance = Wrap({name: 'yfbill', age: 20}, App)
let Instance = Wrap({name: 'yfbill', age: 20})(App)

ReactDom.render(<Instance className="abc"/>, window.root)

 通常來講,高階組件都是以with開頭,通常來講高階組件不會直接渲染到return的內容里面,需要賦值后再進行處理

 

const App: React.FC = () => {
  let Comp = configTag({name: 'yf', age: 10}) return <StyleApp>
    <LayoutHeader/>
    <Content><Comp/></Content>
  </StyleApp>
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM