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