前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[2021-02-24更新]​React Hook使用要点

[2021-02-24更新]​React Hook使用要点

作者头像
zoujunjie202
发布2022-07-27 15:45:11
6520
发布2022-07-27 15:45:11
举报
文章被收录于专栏:zoujunjie202

在官网上,Hook简介的章节里,很安抚性地提到,Hook的提出不旨在替换Class创建组件,而是一种可选、100%向后兼容的特性。然而从使用效果的来说,Hook的应用,解决了render props 和高阶组件组织代码所带来晦涩难懂的窘况,让前端代码代码复用的粒度变得更低,代码可读性更高,研发效率自然也更高。我们团队的新代码,基本都在转向Hook,我也不例外,为了快速翻阅资料,整理以下核心信息,方便高效研发。

【关键点一】只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。

可以阅读这个文章来深入理解:https://juejin.cn/post/6844903850567008270

或者原文 https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e

【关键点二】不可以不学习Class Component而直接学习Hook,否则Hook将会显得非常难理解。

此外,只能在 React 的函数组件或者自定义Hook中调用 Hook。不要在其他 JavaScript 函数中调用。

提纲

  • State Hook 直接对标Class Component中state的功能,更新state的值会触发Function Component的重新渲染
  • Effect Hook 对标的是Class Component中的生命周期,处理componentDidMount、componentDidUpdate 和 componentWillUnmount三种生命周期中的附加行为,也就是副作用
  • 自定义 Hook 对标高阶组件和 render props,在组件之间重用一些状态逻辑,也就是交互行为,可以释放非常多的前端人力
  • Context Hook 不使用组件嵌套就可以订阅 React 的 Context
  • Reducer Hook 通过 reducer 来管理组件本地的复杂 state,一种模仿Redux处理state的方案。
  • Ref Hook 参考Class Component中的ref,用于访问子组件

State Hook

样例代码

代码语言:javascript
复制
import React,{ useState } from'react';
function Example(){
// 声明一个叫 “count” 的 state 变量。
const [count, setCount]=useState(0);
return(
<div>
<p>You clicked {count} times</p>
<buttononClick={()=>setCount(count +1)}> Click me</button>
</div>
);}

useState 唯一的参数就是初始 state

useState 会返回一对值:当前状态和一个让你更新它的函数;

类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并

可以在一个组件中多次使用 State Hook

Effect Hook

样例代码

代码语言:javascript
复制
import React,{ useState, useEffect } from'react';
function Example(){
const [count, setCount] = useState(0);
    useEffect(()=>{
// 组件渲染完毕之后,使用浏览器的 API 更新页面标题 
// 相当于 componentDidMount 和 componentDidUpdate:   
document.title =`You clicked ${count} times`;
const token = setInterval(function(){ alert("Hello"); }, 3000);
return ()=>{
// 清理附加到生命周期的行为,相当于 omponentWillUnmount
            clearInterval(token);
        }
    });
return(<div>
<p>You clicked {count} times</p>
<buttononClick={()=>setCount(count +1)}> Click me </button>
</div>);}

跟 class 组件中的 componentDidMount、componentDidUpdate 和 omponentWillUnmount 具有相同的用途,只不过被合并成了一个 API

可以访问到组件的 props 和 state

副作用函数还可以通过返回一个函数来指定如何“清除”副作用。

跟 useState 一样,你可以在组件中多次使用 useEffect,这带来很清晰、粒度很细的属性和行为控制的能力

自定义 Hook

样例代码

代码语言:javascript
复制
import React, { useState, useEffect } from 'react';
// 一个自定义个Hook,用于侦听好友是否在线和取消侦听,在其他组件中,通过传入friendID既可以复用这里的行为
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  useEffect(() => {
// 启动侦听
    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
// 取消侦听
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });
return isOnline;
}

自定义 Hook 更像是一种约定而不是功能。如果函数的名字以 “use” 开头并调用其他 Hook,我们就说这是一个自定义 Hook。

创建涵盖各种场景的自定义 Hook,如表单处理、动画、订阅声明、计时器、webSocket的管理等。

Context Hook

样例代码

代码语言:javascript
复制
// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
  render() {
// 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
// 无论多深,任何组件都能读取这个值。
// 在这个例子中,我们将 “dark” 作为当前的值传递下去。
return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}
// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar() {
return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// React 会往上找到最近的 theme Provider,然后使用它的值。
// 在这个例子中,当前的 theme 值为 “dark”。
static contextType = ThemeContext;
  render() {
return <Button theme={this.context} />;
  }
}

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定

背景知识:Context 提供了一种在组件之间共享全局值的方式,而不必显式地通过组件树的逐层传递 props,是一种比Redux更老的共享数据的方案。

Reducer Hook

样例代码

代码语言:javascript
复制
// 计数器案例的 Reducer Hook改写方案
const initialState = {count: 0};

function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
  }
}

function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
      Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
  );
}

useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。

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

Ref Hook

样例代码

代码语言:javascript
复制
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus();
  };
return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 zoujunjie202 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Effect Hook
  • Context Hook
  • Reducer Hook
  • Ref Hook
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档