侧边栏壁纸
  • 累计撰写 10 篇文章
  • 累计创建 12 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

react Hooks

枳树
2023-01-17 / 0 评论 / 0 点赞 / 277 阅读 / 1,254 字

react Hooks

一.state hook

1.useState的使用

import React, { useState } from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'




const App = () => {
  const [count, setCount] = useState(0)
  const onClick = (params) => {
    setCount(count + 1)
    console.log(count)
  }
  return (
    <div>
      <div>{count}</div>
      <button onClick={() => onClick()}>button</button>
    </div>
  )
}

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <App />
)

注意

setCount是异步的,console.log(count)会先执行,如果想拿到最新的count,可以使用回调函数的写法。

两种方式

  const onClick = (params) => {
    setCount((count) => count + 1)
  }
  console.log(count)
  const onClick = (params) => {
    setCount((count) => {
    	count++
    	console.log(count)
    	return count
    })
  }

只有在count的值改变时,才会重新渲染。如果setCount中为空对象,则会重新渲染,

因为对象之间对比的是引用即地址,每次设置的地址不同,当然会重新渲染。

如果初始值为一个对象

import React, { useState } from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'


const App = () => {
  const [state, setState] = useState({type: 'add', value: 0})
  
  const onClick = (params) => {
    setState((prevState) => {
        if(prevState.type === 'add'){
            return {
                ...prevState,
                value: prevState.value + 1
            }
        }
        return prevState
    })
  }
  
  return (
    <div>
      <div>{state.value}</div>
      <button onClick={() => onClick()}>button</button>
    </div>
  )
}

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <App />
)

2.useReducer使用

在参数是一个对象时考虑使用useReducer

import React, { useReducer } from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'


const App = (params) => {
    
    const [count, countDispatch] = useReducer(countReducer, 0)
    
    const countReducer = (state, action) => {
        switch(action.type){
            case 'add':
                return state + 1
            case 'minus':
                return state - 1
            default:
                return state
        }
    }
    
  
  const onClick = (params) => {
    countDispatch({type: 'add'})//add描述当前行为
    //countDispatch({type: 'minus'})
  }
  
  return (
    <div>
      <div>{count}</div>
      <button onClick={() => onClick()}>button</button>
    </div>
  )
}

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <App />
)

二. useEffect使用

1.副作用

·引用外部变量,调用外部函数

·拿外部变量,包括修改全局变量(window),修改DOM操作,Ajax请求,计时器,存储相关

·和外部变量的交互

2.用法

useEffect在初次渲染以后执行,会在组件完成更新以后执行,每次都会执行

const App = (params) => {
    
  const [count, setCount] = useState(0)
  console.log("render")
  useEffect(() => {
      console.log("effect")
  })
  
  return (
    <div>
      <div>{count}</div>
      <button onClick={() => onClick()}>button</button>
    </div>
  )
}

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <App />
)

具体的时间点以页面的真实DOM加载为准,在componentDidUpdate真实DOM构建以后,然后执行useEffect,因为useEffect是异步的。

清除Effect

useEffect(() => {
    console.log("useEffect")
    return () => {
        console.log("clear Effect")
    }
})

执行顺序为 render -> clear Effect -> useEffect

清理函数在副作用函数之前运行,在组件销毁的时候同样也会执行

如果只希望在初次渲染时执行,不希望在更新时执行,可以使用依赖项[]

useEffect(() => {
    console.log("开启计时器")
    let timer = setInterval(() => {
        console.log("进入计时器")
        setCount(count => count + 1)//箭头函数
        //setCount(count + 1)
    },1000)
    return () => {
        console.log("清除计时器")
        clearInterval(timer)
    }
},[])

用到了count依赖项,count改变useEffect重新运行,但是又会重新开启新的计时器,最好还是使用箭头函数的方法。

1.指定当前effect函数所需的依赖项。

2.依赖是空数组,在初次渲染和卸载的时候执行。

3.有依赖项,并且依赖项不一直时,会重新执行。

练习

自定义hook

const useCount = params => {
    const [count,setCount] = useState(0)
    useEffect(() => {
    document.title = `You clicked ${count} times`
    console.log("title")
})
    return [count,setCount]
}
const [count,setCount] = useCount()
console.log("render")
useEffect(() => {
    console.log("effect")
})

三.useContext

函数组件用法

import React, {Component, createContext,useContext} from 'react'
import ReactDOM from 'react-dom/client'

const AppContent = createContext()

const Baz = (props) => {
    const value = useContext(AppContent)
    return (
        <div>{value}</div>
    )
}
const App = (params) => {
    return (
        <AppContext.Provider value="xiaoxia">
        	<Baz />
        </AppContext.Provider>
    )
}

四.useRef

const Foo = (params) => {
const inputRef = useRef()
const onClick = (params) => {
    inputRef.current.focus()
}
return (
    <div>
        <input type="text" ref={inputRef}/>
        <button onClick={onClick}>聚焦</button>
    </div>
)
}

const App = (params) => {
    return (
        <div>
            <Foo />
        </div>
    )
}

转发Ref函数组件用法

const Foo = forwardRef((params) => {
//const inputRef = useRef()
const onClick = (params) => {
    inputRef.current.focus()
}
return (
    <div>
        <input type="text" ref={inputRef}/>
        <button onClick={onClick}>聚焦</button>
    </div>
)
})

const App = (params) => {
    const inputRef = createRef()
    const onClick = (params) => {
        inputRef.current.focus()
    }
    return (
        <div>
            <Foo ref={inputRef}/>
            <button onClick={onClick}>父组件</button>
        </div>
    )
}

五.useCallback useMemo

import React, {useState, useMemo,useCallback,memo}  from 'react'

const Foo = memo(props => {
    return (
        <di>{props.count}</di>
    )
})

function App(){
    const [range,setRange] = useState({min:0,max: 10000})
    cosnt [count,setCount] = useState(0)
    
    const render = useCallback((params) => {
        let list = []
        console.log(1)
        for(let i = 0; i <range.max; i++){
            list.push(<li key={i}>{i}</li>)
        }
        return list
    },[range])
    return (
        <div>
            <h1>{count}</h1>
            <button onClick={()=>{setCount(count+1)}}>add</button>
            <Foo render={render}/>
        </div>
    )
}
0

评论区