1. react使用hook的意义
- class组件可以定义自己的state,用来保存组件自己内部的状态,函数式组件不可以,因为函数每次调用都会产生新的临时变量;
-
class组件有 自己的生命周期 ,我们可以在 对应的生命周期中完成自己的逻辑, 比如在componentDidMount中发送网络请求,并且该生命周期函数只会执行一次,如果在函数中发送网络请求,意味着每次重新渲染都会重新发送一次网络请求;
-
class组件可以 在状态改变时只会重新执行render函数 以及 我们希望重新调用的生命周期函数componentDidUpdate 等,函数式组件在重新渲染时,整个函数都会被执行,似乎没有什么地方可以只让它们调用一次;
hook的出现就是为了解决函数式组件中实现class组件的很多特性,它可以让我们在不编写class的情况下使用state以及其他的React特性;
2. useState Hook解析
- 参数:初始化值,如果不设置为undefined;
-
返回值:数组,包含两个元素,元素一: 当前状态的值(第一调用为初始化值) ,元素二: 设置状态值的函数 ;
注意:
- 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用;
- 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用;
import { memo, useState } from "react";
// 普通的函数, 里面不能使用hooks
// 在自定义的hooks中, 可以使用react提供的其他hooks: 必须使用use开头
// function useFoo() {
// const [ message ] = useState("Hello World")
// return message
// }
function CounterHook(props) {
const [counter, setCounter] = useState(0)
const [name] = useState("why")
console.log(name)
// const message = useFoo()
return (
<div>
<h2>当前计数: {counter}</h2>
<button onClick={e => setCounter(counter+1)}>+1</button>
<button onClick={e => setCounter(counter-1)}>-1</button>
</div>
)
}
3. useEffect Hook解析
- Effect Hook 可以让你来完成一些类似于class中生命周期的功能;
-
类似于 网络请求、手动更新DOM、一些事件的监听 ,都是 React更新DOM的一些副作用;
-
对于完成这些功能的Hook被称之为 Effect Hook;
useEffect的解析:
- 通过useEffect的Hook,可以告诉React需要在渲染后执行某些操作;
-
useEffect 要求我们传入一个回调函数 ,在React 执行完更新DOM操作之后 ,就 会回调这个函数;
-
默认情况下, 无论是第一次渲染之后 ,还是每次更新之后,都会 执行这个 回调函数;
清除Effect:
- 比如我们之前的事件总线或Redux中手动调用subscribe;
-
都需要在 componentWillUnmount有对应的取消订阅;
// 负责告知react, 在执行完当前组件渲染之后要执行的副作用代码
useEffect(() => {
// 1.监听事件
// const unubscribe = store.subscribe(() => {
// })
// function foo() {
// }
// 返回值: 回调函数 => 组件被重新渲染或者组件卸载的时候执行
return () => {
}
})
-
某些代码我们只是 希望执行一次即可 ,类似于componentDidMount和componentWillUnmount中完成的事情;(比如网络请求、订阅和取消订阅);
-
多次执行也会导致一定的性能问题;
useEffect的解决方式:
useEffect(() => {
console.log("修改title:", count)
}, [count])
useEffect(() => {
console.log("监听redux中的数据")
return () => {}
}, [])
useEffect(() => {
console.log("监听eventBus的why事件")
return () => {}
}, [])
useEffect(() => {
console.log("发送网络请求, 从服务器获取数据")
return () => {
console.log("会在组件被卸载时, 才会执行一次")
}
}, [])
4. useContext Hook解析
在开发中,要在组件中使用共享的Context有两种方式:
- 类组件可以通过 类名.contextType = MyContext方式,在类中获取context;
-
多个Context或者在函数式组件中通过 MyContext.Consumer 方式共享context;
- Context Hook允许我们通过Hook来直接获取某个Context的值;
contxt.js文章来源:https://www.toymoban.com/news/detail-716591.html
import { createContext } from "react";
const UserContext = createContext()
const ThemeContext = createContext()
export {
UserContext,
ThemeContext
}
App.jsx文章来源地址https://www.toymoban.com/news/detail-716591.html
import React, { memo, useContext } from 'react'
import { UserContext, ThemeContext } from "./context"
const App = memo(() => {
// 使用Context
const user = useContext(UserContext)
const theme = useContext(ThemeContext)
return (
<div>
<h2>User: {user.name}-{user.level}</h2>
<h2 style={{color: theme.color, fontSize: theme.size}}>Theme</h2>
</div>
)
})
export default App
5. useReducer Hook解析
- 在某些场景下,如果state的处理逻辑比较复杂,我们可以通过useReducer来对其进行拆分;
-
或者这次修改的state需要依赖之前的state时,也可以使用;
import React, { memo, useReducer } from 'react'
function reducer(state, action) {
switch(action.type) {
case "increment":
return { ...state, counter: state.counter + 1 }
case "decrement":
return { ...state, counter: state.counter - 1 }
case "add_number":
return { ...state, counter: state.counter + action.num }
case "sub_number":
return { ...state, counter: state.counter - action.num }
default:
return state
}
}
const App = memo(() => {
const [state, dispatch] = useReducer(reducer, { counter: 0, friends: [], user: {} })
return (
<div>
<h2>当前计数: {state.counter}</h2>
<button onClick={e => dispatch({type: "increment"})}>+1</button>
<button onClick={e => dispatch({type: "decrement"})}>-1</button>
<button onClick={e => dispatch({type: "add_number", num: 5})}>+5</button>
<button onClick={e => dispatch({type: "sub_number", num: 5})}>-5</button>
<button onClick={e => dispatch({type: "add_number", num: 100})}>+100</button>
</div>
)
})
export default App
6. useRef Hook解析
- 用法一:引入DOM(或者组件,但是需要是class组件)元素;
-
用法二:保存一个数据,这个对象在整个生命周期中可以保存不变;
import React, { memo, useRef } from 'react'
const App = memo(() => {
const titleRef = useRef()
const inputRef = useRef()
function showTitleDom() {
console.log(titleRef.current)
inputRef.current.focus()
}
return (
<div>
<h2 ref={titleRef}>Hello World</h2>
<input type="text" ref={inputRef} />
<button onClick={showTitleDom}>查看title的dom</button>
</div>
)
})
export default App
到了这里,关于React Hooks解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!