最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React Hooks

    正文概述 掘金(清香的orange)   2021-01-04   417

    React Hooks

    • 有状态的组件没有渲染【hook函数组件返回值不是DOM元素】
    • 有渲染的组件没有状态【hook函数组件没有useState存储状态值】

    为什么使用hooks

    1. useEffect 可以让相同逻辑在同一个地方进行处理【eg:事件的订阅与取消】

    2. Hooks 体现了 React 在组件内部进行逻辑隔离,不像 class 组件的 state 可自定义和跨组件重用。

    3. 可以将组件相同逻辑放置在自定义 hook 中使用【class组件是使用高阶组件 (HOC) 进行逻辑复用的】

    hook的使用规则

    1. 只能在函数最外层调用 hook【不要在循环、条件判断或者子函数中调用】

    2. 只能在 React 的函数组件中调用 hook【或者在**自定义 hook **中使用】

    详情了解见官方文档:https://react.docschina.org/docs/hooks-rules.html

    一、useState【状态钩】

    const [state, setState] = useState(initState) // 函数返回值state命名可以【任意】命名
    
    1. 接受参数: state 的初始值

    2. 返回值:当前 state 值及异步更新 state 的函数 setState( )

    说明:

    1. state只在首次渲染是被创建且赋予初始值 initState【该初始值不仅仅局限于对象】

    2. useState( ) 函数**可以定义多个,**用来保存相应的状态数据信息

    3. 调用更新函数 setState( ) 时,函数组件将重新渲染,并赋予 state 最新的值

    二、useEffect【效果钩(副作用函数)】

    useEffect(() => {}, [param])
    
    1. 接受参数:
    • 参数1:执行操作逻辑函数

    • 参数2:更新 effect 依赖项参数数组

    1. 可选清除订阅机制:操作逻辑函数返回函数中执行清除操作(见说明第2点)

    性能优化:【控制effect的执行(依赖项数组参数)】

    1. 当依赖项数组未设置时,默认每次渲染会更新后执行 effect

    2. 当依赖项参数数组为空时,只在初次渲染后执行 effect

    3. 当 effect 中依赖项参数数组中的值渲染时未发生变化时,则 effect 不会执行更新替换操作

    说明:

    1. 默认情况下,React 会在每次渲染后调用副作用函数 —— 包括第一次渲染的时候【DOM渲染-调用副作用函数-页面展示最新数据信息】

    2. useEffect 可以通过返回一个函数来指定如何“清除”相关的副作用操作,便于将添加和移除订阅的逻辑放在一起

    3. 每次我们重新渲染,默认都会生成新的 effect,替换掉之前的【避免因没有处理更新逻辑而导致常见的 bug】

    4. effect 的清除阶段在每次重新渲染时都会执行,而不是只在卸载组件的时候执行一次

    参考链接

    三、useContext【很多不同层级的组件需要访问同样一些的数据

    import React from 'react';
    
    const MyContext = React.createContext(defaultValue);
    
    // 外层包裹组件
    <MyContext.Provider value={initValue}>
      <MyComponents /> // 可以共享MyContext的数据
    </MyContext.Provider>
    
    
    // 函数子组件 MyComponents
    import React { useContext } from 'react'
    
    function MyComponents() {
       const contextData = useContext(MyContext) // 获取MyContext中的共享数据信息
    }
    
    1. 使用 useContext 结合 userReducer 为顶层组件构建一个全局store
    // context.js
    import React, { createContext } from 'react';
    
    export const Context = createContext();
    
    function reducer(state, action) {
      const { type, payload = {} } = action || {};
      switch(type) {
      	case 'search':
     			return { ...state, params: action.params };
    		case 'update':
    			return Object.assign({}, state, payload);
    		default: 
    			return state;
       }
    }
    
    export function ContextProvider (props) {
      const { state, dispatch } = userReducer(reducer, initialState);
       
      return(
        <Context.Provider value={ { state, dispatch } }>
          { props.children }
        </Context.Provider>
    	)
    }
    
    // 使用的页面
    import React, { useContext } from 'react';
    
    import { Context, ContextProvider } from 'context';
    
    const { state, dispatch } = useContext(Context);
    
    export default function MyPage() {
      return (
        <ContextProvider>
          <MyComponents />
        </ContextProvider>
      )
    }
    

    说明:

    1. useContext(MyContext) 只可以帮助我们获取 context 值和订阅 context 的变化,仍然需要在上层组件中使用 Provider 来提供context, 并且多个 Provider 可以相互嵌套使用

    2. 当 react 渲染订阅了 context 的组件时,该组件会从距离他**最近的 Provider 中获取当前的 context【initValue】**值, 若没有匹配到相应的 Provider 则 defaultValue 生效

    3. undefined 传递给 Provider 的 value 时,消费组件的 defaulValue 不会生效

    4. Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染

    四、unstated-next【React轻量状态管理库】(结合 useReducer)

    基本使用:

    /**
     * 1. 使用 createContainer 构建存储容器
     **/
    
    import { createContainer } from "unstated-next"
    
    // 定义一个reducer纯函数处理相应逻辑并更新 state
    function reducer(state, action) {
      switch(action.type) {
        case 'add':
          return { ...state, propName: action.payload };
        default:
          return state;
      }
    }
    
    
    // 
    function useLocalStore() {
      const [state, dispatch] = useReducer(reducer, initialState);
      return {
        state,
        dispatch
      }
    }
    
    export default const Store = createContainer(useLocalStore);
    
    
    /**
     * 2. 需使用该 store.Provider 包裹需要使用 store 的使用的组件
     */
    import Store from './filePathName';
    <Store.Provider>
      <Components />  // 需要使用该轻量级仓库的组件
    </Store.Provider>
    
    /**
     * 3. 在需要的页面中使用
     **/
    import Store from ‘./filePathName’;
    
    const { state: { initCount }, dispatch } = Store.useContainer();
    
    /**
     * 4. 解决多层container嵌套问题
     **/
    <Container1.Provider>
      <Container2.Provider>
       <Container3.Provider>
    	   MyApp
       </Container3.Provider>
      </Container2.Provider>
    </Container1.Provider>
    
    **修改为:**
    
    function compose(...containers) {
    	return function Component(props) {
    		return containers.reduceRight((children, Container) => {
    			return <Container.Provider>{children}</Container.Provider>
    		}, props.children)
     	}
    }
    
    let Provider = compose(Container1, Container2,Container1);
    
    <Provider >
      myApp
    </Provider>
    
    /**
     * 5. useReducer简单内部构建
     */
    function useReducer(reducer, initialState) {
    	const [state, setState] = useState(initialState);
    	function dispatch(action) {
     		const nextState = reducer(state, action);
      	setState(nextState);
    	}
    	return [state, dispatch];
    }
    
    useReducer(reducer, initialArg, init);
    
    1. 指定初始state
    useReducer(reducer, { count: initCount });
    
    • initialArg:容器库 initState 对象
    1. 惰性初始化
    useReducer(reducer, initCount, function(initCount) { return {count: initCount} })
    
    • initialArg:init 函数的参数值

    • init 函数:可以用于对初始数据信息执行一些逻辑操作

    function reducer(state, action) {
      const { payload = {} } = action || {};
      return {
        ...state,
       	...payload,
      }
    }
    
    const [query, setQuery] = useReducer(reducer, {
      pageNo,
      pageSize,
      createAt,
      ...
    })
    
    // 使用时
    setQuery({ payload: { …query, pageNo:_pageNo } })
    

    说明:

    1. React 会确保 dispatch 函数的标识是稳定的,并且不会在组件重新渲染时改变

    2. 当 Reducer Hook 的返回值与当前 state 相同,React 将跳过子组件的渲染及副作用的执行

    参考链接

    五、 useCallback(主要用于处理对于一些数据更新引起其他组件不必要的渲染)

    const memoizedCallback = useCallback(() => {
    		doSomething(a, b);
    	}, [a, b]);
    
    1. 返回值:返回一个memoized回调函数

    2. 接受参数:

    • 参数1::内联函数

    • 参数2:依赖项数组

    说明:

    1. 只有当依赖项发生改变时,内联回调函数中的值才会得到最新值。否则,内联回调函数中的变量都是之前时侯的值。

    2. 当传入空数组时,该返回的memoized回调函数一直不会发生改变。

    参考链接

    六、useMemo【优化避免在每次渲染时都进行高开销的计算逻辑

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    
    1. 返回值:返回一个memoized值

    2. 接受参数:

    • 参数1::“创建”函数

    • 参数2:依赖项数组

    说明:

    1. 若没有提供依赖项,useMemo在每次渲染时都会计算新的值

    2. 若提供依赖项数组,当某个依赖项改变时才会重新计算memoized值

    3. 不要在该“创建”函数内部执行与渲染无关的操作【如副操作等适合使用在其它hook中的逻辑】

    七、useRef

    const refContainer = useRef(initialValue);
    
    1. 返回值:返回一个可变的 ref 对象,返回的该 ref 对象在组件的整个生命周期内保持不变

    2. 返回可变的ref对象的 current 属性初始化值为 useRef 传入的参数值(initialValue)

    作用:

    • 获取组件实例对象或DOM对象

    • 可以跨渲染周期保存数据

    说明:

    1. 当 ref 对象内容发生变化时,useRef 并不会通知你

    2. 变更 .current 属性不会引发组件重新渲染

    3. 想要在 React 绑定或解绑 DOM 节点的 ref 时运行某些代码,则需要使用回调 ref 来实现

    React.forwardRef

    具体实例参考链接

    八、useImperativeHandle【避免暴露过多属性给父组件】

    function FancyInput(props, ref) {
     const inputRef = useRef();
      
     useImperativeHandle(ref, () => ({
      focus: () => {
       inputRef.current.focus();
      }
     }));
    
     return <input ref={inputRef} ... />;
    }
    
    FancyInput = forwardRef(FancyInput);
    
    useImperativeHandle(ref, createHandle, [deps])
    
    1. 接受参数:
    • 参数1: 接收一个通过forwardRef引用父组件的ref实例

    • 参数2:回调函数,返回一个对象,对象里面存储需要暴露给父组件的属性或方法

    说明:

    1. 官方建议 useImperativeHandle 应当与 forwardRef 一起使用,避免使用 ref 那样的命令式代码

    2. 当我们不想向父组件暴露太多的东西的时候,可以使用 useImperativeHandle按需暴露给父组件一些东西

    九、useLayoutEffect【**在所有的 **DOM 变更之后同步调用 effect】

    什么情况下使用:

    说明:

    1. 在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新

    2. 建议尽可能使用标准的 useEffect 以避免阻塞视觉更新

    十、useDebugValue 【在react的浏览器调试工具上显示你的自定义hooks,或者给hooks标记一些东西】

    useDebugValue(value[, callback]);
    

    接受参数:

    • 参数1:参数标记在react的调试工具上

    • 参数2:回调函数,函数形参为useDebugValue的第一个参数,返回值会显示在浏览器调试工具中【回调函数中可以进行一系列操作】

    各hook的具体实例理解可以参考下面???

    参考链接


    起源地下载网 » React Hooks

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元