博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
react hooks 学习笔记
阅读量:6083 次
发布时间:2019-06-20

本文共 4697 字,大约阅读时间需要 15 分钟。

这篇为react hooks的学习笔记,仅对需要关注的重点做了记录。有关react hooks详细说明,参见官网

Rules of Hooks

  • 不能将 hooks 放在循环、条件语句或者嵌套方法内。react是根据hooks出现顺序来记录对应状态的
  • 只在 function 组件和自定义 hooks 中使用 hooks。
  • 命名规范

    • useState 返回数组的第二项以 set 开头(仅作为约定)
    • 自定义 hooks 以 use 开头(可被 lint 校验)

API

  • useState

    useState 可传任意类型的变量或者返回任意类型变量的 function。
    useState 返回数组的第二个参数(setter),可传任意类型的变量,或者一个接收 state 旧值的 function,其返回值作为 state 新值

    function Counter({ initialCount }) {  const [count, setCount] = useState(initialCount);  // Lazy initialization  const [state, setState] = useState(() => {    const initialState = someExpensiveComputation(props);    return initialState;  });  return (    <>      Count: {count}                        );}

    set 方法不会像 setState 一样做 merge,所以建议如果数据结构简单,可以将变量根据数据结构需要放在不同的 useState 中,避免大量使用类似{...state, value}形势。如果数据结构复杂,建议使用 useReducer 管理组件的 state

  • useEffect

    useEffect(effect, array);

    effect 函数将在 componentDidAmount 时触发和 componentDidUpdate 时有条件触发。可以返回一个函数(returnFunction),returnFunction 将会在 componentWillUnmount 时触发和在 componentDidUpdate 时先于 effect 有条件触发。

    与 componentDidAmount 和 componentDidUpdate 不同之处是,effect 函数触发时间为在浏览器完成渲染之后。 如果需要在渲染之前触发,需要使用 useLayoutEffect。
    第二个参数 array 作为有条件触发情况时的条件限制。

    • 如果不传,则每次 componentDidUpdate 时都会先触发 returnFunction(如果存在),再触发 effect。
    • 如果为空数组[],componentDidUpdate 时不会触发 returnFunction 和 effect。
    • 如果只需要在指定变量变更时触发 returnFunction 和 effect,将该变量放入数组。
  • useContext

    和consumer类似,仍然需要与Provider配合使用

    const Context = React.createContext('light');// Providerclass Provider extends Component {  render() {    return (      
    ) }}
    // Consumerfunction Consumer(props) {  const context = useContext(Context);  return (    
    {context} // dark
    );}
  • useReducer

    用于管理复杂结构的状态对象,与redux的核心逻辑一致。

    const [state, dispatch] = useReducer(reducer, initialState, {  type: 'reset',  payload: initialCount});
    // democonst TodosDispatch = React.createContext(null);function TodosApp() {  // Tip: `dispatch` won't change between re-renders  const [todos, dispatch] = useReducer(todosReducer, initialState);  return (    
    );}
  • useCallback

    useCallback和下面的useMemo是非常实用的提升性能的小工具。

    const memoizedCallback = useCallback(  () => {    doSomething(a, b);  },  [a, b]);

    useCallback返回一个函数,在参数a和b都没有改变时,总是返回同一个函数。

    其具体实现逻辑基本如下:

    let memoizedState = null;function useCallback(callback, inputs) {  const nextInputs =    inputs !== undefined && inputs !== null ? inputs : [callback];  const prevState = memoizedState;  if (prevState !== null) {    const prevInputs = prevState[1];    if (areHookInputsEqual(nextInputs, prevInputs)) {      return prevState[0];    }  }  memoizedState = [callback, nextInputs];  return callback;}

    注:第二个参数目前只用于指定需要判断是否变化的参数,并不会作为形参传入回调函数。建议回调函数中使用到的变量都应该在数组中列出。以后的版本可能会将第二项数组参数移除,自动判断回调函数中使用到的变量是否变化来判断返回结果。

  • useMemo

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

    与useCallback类似,返回一个memoized函数执行结果。

    useMemo(() => fn, inputs) 等价于 useCallback(fn, inputs)
    useMemo可用于实现PureComponent子组件:

    function Parent({ a, b }) {  // Only re-rendered if `a` changes:  const child1 = useMemo(() => 
    , [a]); // Only re-rendered if `b` changes: const child2 = useMemo(() =>
    , [b]); return ( <> {child1} {child2} )}
  • useRef

    const refContainer = useRef(initialValue);

    类似 react.createRef()。

    在使用hooks的function component中,useRef不仅可以用来做DOM的引用,还可以做来作为类似class的实例属性,因为相同位置的useRef()每次返回的都是同一个对象。

    function Timer() {  const intervalRef = useRef();  useEffect(() => {    const id = setInterval(() => {      // ...    });    intervalRef.current = id;    return () => {      clearInterval(intervalRef.current);    };  });  // ...}

    利用useRef()的这种特性,还可以做很多其他有趣的事情,例如获取previous props或previous state:

    function Counter() {  const [count, setCount] = useState(0);  const prevCountRef = useRef();  useEffect(() => {    prevCountRef.current = count;  });  const prevCount = prevCountRef.current;  return 

    Now: {count}, before: {prevCount}

    ;}
  • useImperativeMethods

    function FancyInput(props, ref) {  const inputRef = useRef();  useImperativeMethods(ref, () => ({    focus: () => {      inputRef.current.focus();    }  }));  return ;}FancyInput =  React.forwardRef(FancyInput);

    useImperativeMethods提供了父组件直接调用子组件实例方法的能力。

    上例中,一个包含 <FancyInput ref={fancyInputRef} /> 的父组件,就可以调用 fancyInputRef.current.focus().

Tips

  • 目前暂时没有与getSnapshotBeforeUpdate和componentDidCatch相匹配的hooks。
  • 使用ESlint plugin(eslint-plugin-react-hooks)做代码校验。
  • Hooks的调用只能放在function component(首字母大写的function)或者自定义Hook(名为useXxxx的function)中。
  • Hooks在组件的每次render时都以完全相同的顺序执行。
  • 用React.memo来实现shouldComponentUpdate。

    const Button = React.memo((props) => {  // your component});
  • 请将refs理解成class中的实例属性。

转载地址:http://kmkwa.baihongyu.com/

你可能感兴趣的文章
启动jetty命令
查看>>
C#获取当前时间与同步时间
查看>>
端口被占用了,使用netstat找到占用端口的进程
查看>>
springboot的profile配置
查看>>
c++ 指针与 typedef
查看>>
委托-匿名方法-Lambda表达式
查看>>
MPF配置文件参数管理
查看>>
四则运算程序生成
查看>>
PIE SDK矢量数据的创建
查看>>
洛谷p1064 金明的预算方案
查看>>
10步让你成为更优秀的程序员
查看>>
杭电ACM 2013
查看>>
CF10E Greedy Change 判断硬币系统是否能用贪心策略
查看>>
坑人的开发——记一次私活的坑人经历
查看>>
sys用户无法远程登陆
查看>>
加速原型设计
查看>>
Android中文API(145) —— NotificationManager
查看>>
JS DateTime 格式化
查看>>
ASP.NET RSA 加密
查看>>
数据库优化设计方案
查看>>