自己怎样做免费网站,i网站建设,网站策划书网站需求分析,做网站主要注意些什么Hooks函数
1.useState()#xff1a;状态钩子。纯函数组件没有状态#xff0c;用于为函数组件引入state状态, 并进行状态数据的读写操作。
const [state, setState] useState(initialValue);
// state#xff1a;初始的状态属性#xff0c;指向状态当前值#xff0c;类似…Hooks函数
1.useState()状态钩子。纯函数组件没有状态用于为函数组件引入state状态, 并进行状态数据的读写操作。
const [state, setState] useState(initialValue);
// state初始的状态属性指向状态当前值类似this.state
// setState修改状态属性值的函数用来更新状态类似setState
// initialValue状态的初始值该值会赋给state
注意setState的命名为setState(初始状态名)并且采用小驼峰命名法。例如[count, setCount]
示例实现计数器
const Count () {const [count, setCount] useState(0); // 将0设置为count的初始值const addCount () {let newCount count;setCount(newCount 1);}return (divp{count}/pbutton onClick{addCount}加1/button/div)
}
用函数组件实现了一个功能完全一样的计数器代码看起来更加的轻便简洁没有了继承没有了渲染逻辑没有了生命周期等。这就是hooks存在的意义。
useEffect()副作用钩子。用来更好的执行副作用操作(用于模拟类组件中的生命周期钩子)如异步请求等在类组件中会把请求放在componentDidMount里面在函数组件中可以使用useEffect()
useEffect(() {// 回调函数其中是要进行的异步操作代码
}, [array])
// [array]useEffect执行的依赖当该数组的值发生改变时回调函数中的代码就会被指向
// 如果[array]省略则表示不依赖在每次渲染时回调函数都会执行
// 如果[array]是空数组即useEffect第二项为[]表示只执行一次
示例通过useEffect()模拟异步加载数据第二项省略。
const AsyncPage () {// 首先设置loading状态为trueconst [loading, setLoading] useState(true);useEffect(() {// 2秒后将loading状态设置为falsesetTimeout(() {setLoading(false);}, 2000);})return (// 判断loading是否为true是就显示loading不是就显示异步请求完成loading ? ploading.../p : p异步请求完成/p)
}
示例useEffect()依赖第二项数组变化
const AsyncPage ({name}) {const [loading, setLoading] useState(true); // 设置loading状态为trueconst [person, setPerson] useState({}); // 设置person状态为空对象useEffect(() {// 首先设置loading为true2秒后改为falsename改成传过来的参数setLoading(true);setTimeout(() {setLoading(false);setPerson({name});}, 2000);}, [name]); // 表示当name修改才会执行回调函数return ({loading ? pLoading.../p : p{person.name}/p}/)
}const PersonPage () {// 设置初始state为空字符串const [state, setState] useState();const changeName (name) { // 修改name的函数setState(name);}return ({/*首先将state传给name*/}AsyncPage name{state}/button onClick{() { // 点击按钮后将张三传给namechangeName(张三)}}张三/buttonbutton onClick{() {changeName(李四)}}李四/button/)
}
useEffect和useLayoutEffect的区别 useEffect()和useLayoutEffect()主要的区别是调用时机不同。
useLayoutEffect()和componentDidMount()及componentDidUpate()一致再react完成DOM更新后马上同步调用代码它会阻塞页面的渲染而useEffect()则会在页面渲染完后才会异步调用。
在实际使用中如果项避免页面抖动可以把需要操作DOM的代码放在useLayoutEffect()中在该函数中做DOM操作这些DOM修改会和react做出的更改一起被一次性渲染到屏幕上只有一次回流重绘的代价。
useContext()共享状态钩子。useContext()可以共享状态作用是进行状态的分发React16.x以后的版本支持避免了使用Props进行数据的传递。
Context一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信创建Context容器对象
const XxxContext React.createContext() 渲染子组件时外面包裹xxxContext.Provider 通过value属性给后代组件传递数据
xxxContext.Provider value{数据}子组件/
/xxxContext.Provider后代组件读取数据
const {} useContext(XxxContext)示例父组件和子组件共享一个状态 index.tsx 为父组件demo.tsx为子组件
// index.tsx
import { createContext, useState } from react;
import Demo from ./Demo/demo;// createContextAPI对象
// const context变量名称 createContext();
//这里要使用export导出不然子组件不能引用context
export const context createContext(0);export default function App() {const [count, setCount] useState(0);const add () {setCount(count 1);};return (divdiv计数器{count}次/divbutton onClick{add}1/button{/* 共享数据 把count的值共享给Demo组件 */}context.Provider value{count}Demo/Demo/context.Provider/div);
}demo.tsx
import { useContext } from react;
//引入 const context createContext();
import { context } from ../index;
export default function Index() {//接收context的数据给conconst con useContext(context);return div接受父组件的{con}数据/div;
}useReducer()Action钩子。在使用React的过程中如遇到状态管理一般会用到Redux。而React本身是不提供状态管理的。而useReducer() 提供了状态管理。 useReducer()是useState()的替代方案。首先关于redux我们都知道其原理是通过用户在页面中发起action从而通过reducer方法来改变state从而实现页面和状态的通信。而Reducer的形式是(state, action) newstate返回当前的 state 以及与其配套的 dispatch 方法。
语法格式 const [state, dispatch] useReducer(reducer, initialState)参数、返回值说明
它接受 reducer函数 和 状态的初始值 作为参数返回一个数组其中第一项为当前的状态值第二项为发送action的dispatch函数。
在某些场景下useReducer 会比 useState 更适用例如 state 逻辑较复杂且包含多个子值或者下一个 state 依赖于之前的 state 等。并且使用 useReducer 还能给那些会触发深更新的组件做性能优化因为可以向子组件传递 dispatch 而不是回调函数。
例如使用useReducer()实现一个计数器
import { useReducer } from react;
const HookReducer () {const reducer (state,action) {if (action.type add) {return {...state,count: state.count 1}}else {return state}}const addCount () {dispatch({type: add})}const [state,dispatch ] useReducer(reducer,{count: 0})return (p{state.count}/pbutton onClick{ addCount }1/button/)
}
export default HookReducer;
通过代码可以看到使用useReducer()代替了Redux的功能但useReducer无法提供中间件等功能假如有这些需求还是需要用到redux。
useRef()保存引用值。
const refContainer useRef()
useRef返回一个可变的ref对象useRef接受一个参数绑定在返回的ref对象的current属性上返回的ref对象在整个生命周期中保持不变。
例子input上绑定一个ref使得input在渲染后自动焦点聚焦
import{ useRef,useEffect} from react;
const RefComponent () {let inputRef useRef(null);useEffect(() {inputRef.current.focus();})return (input typetext ref{inputRef}/)
}
useCallback() 记忆函数主要是为了性能的优化,可以防止因为组件重新渲染导致方法被重新创建起到缓存作用。
useCallback(() {// 回调函数当array改变后该函数才会重新声明
}, [array])
// 如果[array]为空数组那么就是第一次创建后就被缓存如果后期array改变了拿到的还是老的array
// 如果不传入第二个参数每次都会重新声明一次拿到的就是最新的array
useCallback(fn, deps) 相当于 useMemo(() fn, deps)
可以认为是对依赖项的监听接受一个回调函数和依赖项数组。
1.useCallback会返回一个函数的memoized(记忆的)值。 2.该回调函数仅在某个依赖项改变时才会 3.在依赖不变的情况下多次定义的时候返回的值是相同的
import {useState,useCallback} from react;const CallbackComponent () {let [count, setCount] useState(1);let [num, setNum] useState(1);const memoized useCallback(() {return num;}, [count])console.log(记忆, memoized());console.log(原始, num);return (button onClick{() {setCount(count 1)}} count/buttonbutton onClick{() {setNum(num 1)}} num/button/)
}
export default CallbackComponent
比如说下面一段代码中我们可以看到有很多的函数当我们在return中修改一个状态就会导致整个页面重新渲染那么这些函数handleChange1、handleChange2…也会被重新创建这样会造成性能的浪费因此可以使用useCallback将这些函数缓存下来这样下一次页面重新渲染的时候某些函数就不会重新被创建了。 const UseCallback function () {const handleChange1 () {// 具体代码}const handleChange2 () {// 具体代码}const handleChange3 () {// 具体代码}const handleChange4 () {// 具体代码}return (div{/*具体代码*/}/div)}
使用useCallback()时只需要将其写在整个函数外部即可上面代码使用useCallback()后效果如下每当依赖项改变时该函数才会被重新创建如果依赖项不变则不会重新创建。 const UseCallback function () {const handleChange1 useCallback(() {// 具体代码}, [依赖项])const handleChange2 useCallback(() {// 具体代码}, [依赖项])const handleChange3 useCallback(() {// 具体代码}, [依赖项])const handleChange4 useCallback(() {// 具体代码}, [依赖项])return (div{/*具体代码*/}/div)}
useMemo()记忆组件主要用来解决使用React hooks产生的无用渲染的性能问题。
**useCallback()的功能可以由useMemo()所替代useMemo()**也可以返回一个记忆函数语法如下
useMemo(() fn, [])
// useCallback(fn, []) useMemo(() fn, [])
语法和参数说明
const cacheSomething useMemo(create,deps)
create第一个参数为一个函数函数的返回值作为缓存值deps 第二个参数为一个数组存放当前 useMemo 的依赖项在函数组件下一次执行的时候会对比 deps 依赖项里面的状态是否有改变如果有改变重新执行 create 得到新的缓存值。cacheSomething返回值执行 create 的返回值。如果 deps 中有依赖项改变返回的重新执行 create 产生的值否则取上一次缓存
使用function的形式来声明组件失去了shouldCompnentUpdate在组件更新之前这个生命周期也就是说没有办法通过组件更新前条件来决定组件是否更新。
而且在函数组件中也不再区分mount和update两个状态这意味着函数组件的每一次调用都会执行内部的所有逻辑就带来了非常大的性能损耗。
useMemo原理
useMemo 会记录上一次执行 create 的返回值并把它绑定在函数组件对应的 fiber 对象上只要组件不销毁缓存值就一直存在但是 deps 中如果有一项改变就会重新执行 create 返回值作为新的值记录到 fiber 对象上。
useMemo应用场景
可以缓存 element 对象从而达到按条件渲染组件优化性能的作用。如果组件中不期望每次 render 都重新计算一些值可以利用 useMemo 把它缓存起来。可以把函数和属性缓存起来作为 PureComponent 的绑定方法或者配合其他Hooks一起使用
useCallback()与useMemo()的区别
useCallback()不会执行第一个参数函数而是将其返回useMemo()会执行第一个函数并且将函数执行结果返回给你。useCallback()常用记忆时间按函数生成记忆后的时间函数传递给子组件使用useMemo()更适合经过函数计算得到一个确定的只比如记忆组件。
useLayoutEffect() 和useEffect相同都是用来执行副作用但是它会在所有的DOM变更之后同步调用effect。useLayoutEffect和useEffect最大的区别就是一个是同步一个是异步。
从这个Hook的名字上也可以看出它主要用来读取DOM布局并触发同步渲染在浏览器执行绘制之前useLayoutEffect 内部的更新计划将被同步刷新。
官网建议还是尽可能的是使用标准的useEffec以避免阻塞视觉更新。
useImperativeHandle() 可以在使用 ref 时自定义暴露给父组件的实例值。
就是说当使用父组件把ref传递给子组件的时候这个Hook允许在子组件中把自定义实例附加到父组件传过来的ref上有利于父组件控制子组件。
import {useEffect,useRef,useImperativeHandle} from react;
import {forwardRef} from react;function FancyInput(props, ref) {const inputRef useRef();useImperativeHandle(ref, () ({focus: () {inputRef.current.valueHello;}}));return input ref{inputRef} /;
}
FancyInput forwardRef(FancyInput);const ImperativeHandleTest() {let ref useRef(null);useEffect(() {console.log(ref);ref.current.focus();})return (FancyInput ref{ref}//)
}
export default ImperativeHandleTest
自定义Hooks
有时候我们需要创建自己想要的Hooks来满足更便捷的开发就是根据业务场景对其它Hooks进行组装从而得到满足自己需求的钩子。
自定义 Hooks是一个函数其名称以 “use” 开头函数内部可以调用其他的 Hook
自定义Hooks可以封装状态能够更好的实现状态共享
自定义hooks可以说成是一种约定而不是功能。当一个函数以use开头并且在函数内部调用其他hooks那么这个函数就可以成为自定义hooks
import { useState,useEffect } from react;
const usePerson ({name}) {const [loading, setLoading] useState(true)const [person, setPerson] useState({})useEffect(() {setLoading(true)setTimeout(() {setLoading(false)setPerson({name})},2000)},[name])return [loading,person]
}
const AsyncPage (name) {const [loading,person] usePerson(name)return ({loading?pLoading.../p:p{ person.name }/p}/)
}const PersonPage () {const [state,setState] useState()const changeName (name) {setState(name)}return (AsyncPage name{ state } /button onClick{ () { changeName(郭靖)}}郭靖/buttonbutton onClick{ () { changeName(黄蓉)}}黄蓉/button/)
}
export default PersonPage;
上面代码中封装成了自己的Hooks便于共享。其中usePerson()为自定义Hooks它接受一个字符串返回一个数组数组中包括两个数据的状态之后在使用usePerson()时会根据传入的参数不同而返回不同的状态然后很简便的应用于我们的页面中。
这是一种非常简单的自定义Hook。如果项目大的话使用自定义Hook会抽离可以抽离公共代码极大的减少我们的代码量提高开发效率。