React中的Hooks
船长在船上 人气:0Hooks进阶
useState - 回调函数的参数
使用场景
参数只会在组件的初始渲染中起作用,后续渲染时会被忽略。如果初始 state 需要通过计算才能获得,则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用
语法
const [name, setName] = useState(()=>{ // 编写计算逻辑 return '计算之后的初始值'})
语法规则
- 回调函数return出去的值将作为
name
的初始值 - 回调函数中的逻辑只会在组件初始化的时候执行一次
语法选择
- 如果就是初始化一个普通的数据 直接使用
useState(普通数据)
即可 - 如果要初始化的数据无法直接得到需要通过计算才能获取到,使用
useState(()=>{})
需求
import { useState } from 'react' function Counter(props) { const [count, setCount] = useState(() => { return props.count }) return ( <div> <button onClick={() => setCount(count + 1)}>{count}</button> </div> ) } function App() { return ( <> <Counter count={10} /> <Counter count={20} /> </> ) } export default App
useEffect - 清理副作用
使用场景
在组件被销毁时,如果有些副作用操作需要被清理,就可以使用此语法,比如常见的定时器
语法及规则
useEffect(() => { console.log('副作用函数执行了') // 副作用函数的执行时机为: 在下一次副作用函数执行之前执行 return () => { console.log('清理副作用的函数执行了') // 在这里写清理副作用的代码 } })
定时器示例
添加副作用函数前:组件虽然已经不显示了,但是定时器依旧在运行
import { useEffect, useState } from 'react' function Foo() { useEffect(() => { setInterval(() => { console.log('副作用函数执行了') }, 1000) }) return <div>Foo</div> } function App() { const [flag, setFlag] = useState(true) return ( <> <button onClick={() => setFlag(false)}>click</button> {flag ? <Foo/> : null} </> ) } export default App
添加清理副作用函数后:一旦组件被销毁,定时器也被清理
import { useEffect, useState } from 'react' function Foo() { useEffect(() => { const timerId = setInterval(() => { console.log('副作用函数执行了') }, 1000) // 添加清理副租用函数 return () => { clearInterval(timerId) } }) return <div>Foo</div> } function App() { const [flag, setFlag] = useState(true) return ( <> <button onClick={() => setFlag(false)}>click</button> {flag ? <Foo/> : null} </> ) } export default App
useEffect - 发送网络请求
使用场景
如何在useEffect中发送网络请求,并且封装同步 async await操作
语法要求
不可以直接在useEffect的回调函数外层直接包裹 await ,因为异步会导致清理函数无法立即返回
useEffect(async ()=>{ const res = await axios.get('http://geek.itheima.net/v1_0/channels') console.log(res) },[])
正确写法
在内部单独定义一个函数,然后把这个函数包装成同步
useEffect(()=>{ async function fetchData(){ const res = await axios.get('http://geek.itheima.net/v1_0/channels') console.log(res) } },[])
useRef
本节任务:
能够掌握使用useRef获取真实dom或组件实例的方法
使用场景
在函数组件中获取真实的dom元素对象或者是组件对象
使用步骤
- 导入
useRef
函数 - 执行
useRef
函数并传入null,返回值为一个对象 内部有一个current属性存放拿到的dom对象(组件实例) - 通过ref 绑定 要获取的元素或者组件
获取dom
import { useEffect, useRef } from 'react' function App() { const h1Ref = useRef(null) useEffect(() => { console.log(h1Ref) },[]) return ( <div> <h1 ref={ h1Ref }>this is h1</h1> </div> ) } export default App
获取组件实例
函数组件由于没有实例,不能使用ref获取,如果想获取组件实例,必须是类组件
Demo.js
class Foo extends React.Component { sayHi = () => { console.log('say hi') } render(){ return <div>Foo</div> } } export default Foo
App.js
import { useEffect, useRef } from 'react' import Foo from './Demo' function App() { const h1Foo = useRef(null) useEffect(() => { console.log(h1Foo) }, []) return ( <div> <Foo ref={ h1Foo } /></div> ) } export default App
useContext
实现步骤
- 使用
createContext
创建Context对象 - 在顶层组件通过
Provider
提供数据 - 在底层组件通过
useContext
函数获取数据
代码实现
import { createContext, useContext } from 'react' // 创建Context对象 const Context = createContext() function Foo() { return <div>Foo <Bar/></div> } function Bar() { // 底层组件通过useContext函数获取数据 const name = useContext(Context) return <div>Bar {name}</div> } function App() { return ( // 顶层组件通过Provider 提供数据 <Context.Provider value={'this is name'}> <div><Foo/></div> </Context.Provider> ) } export default App
加载全部内容