react hook的常用方法及用例

1,985 阅读3分钟

react hook的常用方法

useState、useEffect、useCallback、useMemo、useRef, 以及自定义hook

每个方法的如何使用?

以下方法说明及用例多自出自官方文档 传送门

useState

useState相当于class的state的赋值操作

import React, { useState } from 'react';

function Example() {
  // 声明一个叫 "count" 的 state 变量
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

// 等价于class的用法
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

useEffect

如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。

1.没有依赖变量的情况下

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
    return () => {
      document.title = `leave current`;
    };
  }, []);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
// class的形式
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }

  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentWillUnmount{
    document.title = `leave current`;
  }
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

2.依赖变量的情况下

// 对上面的例子做下修改,假设接受一个count变量
function Example({count}) {
  useEffect(() => {
    // 根据id获取商品详情的http请求等操作
    return () => {
      // 解耦操作防止内存泄漏
    };
  }, [count]);

  return (
    <div>
      // something
    </div>
  );
}

useMemo

用于缓存计算结果。类似vue的计算属性,函数只依赖count的变化

import React, { useState, useMemo } from "react";

function Page() {
	const [count, setCount] = useState(1);
	const expensive = useMemo(() => {
		console.log("compute");
		let sum = 0;
		for (let i = 0; i < count * 100; i += 1) {
			sum += i;
		}
		return sum;
	}, [count]);

	return (
		<div>
			<h4>
				{count}-{expensive}
			</h4>
			<div>
				<button type="button" onClick={() => setCount(count + 1)}>
					add
				</button>
			</div>
		</div>
	);
}

export default Page;

useCallback

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

import React, { useState, useCallback } from "react";

function Page() {
	const [count, setCount] = useState(1);
	function calculate(count) {
		let sum = 0;
		for (let i = 0; i < count * 100; i += 1) {
			sum += i;
		}
		return sum;
	}
	const expensive = useCallback(calculate(count), [count]);

	return (
		<div>
			<h4>
				{count}-{calculate(count)}
			</h4>
			<div>
				<button type="button" onClick={() => setCount(count + 1)}>
					add
				</button>
			</div>
		</div>
	);
}

export default Page;

useRef

相当于class中的this
function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus();
  };
  useEffect(() => {
    return () => {
	  console.log(inputEl.current);
	  inputEl.current = null;
	  console.log(inputEl.current);
    };
  })
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

自定义hook

它的名字应该始终以 use 开头,这样可以一眼看出其符合 Hook 的规则。 自定义hook在我理解的就是共享逻辑的封装,然后自定义hook不会共享 state,每一次引用都是完全独立的对象。return 一个对象或一个值。

下面为个简单的例子

// commonHook/index.js
import React, { useState, useEffect, useCallback } from "react";

function useWinSize() {
	const [size, setSize] = useState({});

	const onResize = useCallback(() => {
		setSize({
			width: document.documentElement.clientWidth,
			height: document.documentElement.clientHeight,
		});
	}, []);

	useEffect(() => {
		window.addEventListener("resize", onResize);
		return () => {
			console.log("remove");
			window.removeEventListener("resize", onResize);
		};
	}, []);
	return size;
}
export default useWinSize;

// 在需要使用的地方
import React from "react";
import useWinSize from "../commonHook/index";

function Example() {
	const size = useWinSize();
	return (
          <div>
    	    自定义hook作为公共的逻辑处理,相当于一个函数,返回一个值或对象。
    	    Page size: {size.width} * {size.height}
	  </div>
	);
}

export default Example;