React hooks

hooks 的作用

可以在 function component 中使用 hooks,如 useState、useContext 等,让它具有 class 才具有的一些特性。并且在 class 中,hooks 是不管用的,因此不能使用。

useState

state hooks

import React, { useState } from 'react';

function Example(props) {
  // useState 返回一对:当前状态值和一个允许更新它的函数, 这一对的名字可以随便取,并且不会像 class 中的 state 必须是一个 object。可以是一个普通的值。
  const [count, setCount] = useState(0/* initial state*/);
  // 可以调用多次,生成多个 state, 它们之间互不影响。
  const [person, upPerson] = useState({ name: 'longjicnen', age: 21}/* initial state*/);
  return (
  <div>
  	<button onClick={() => this.setState(count + 1 )}>
    Click me
  	</button>
  	<button onClick={() => this.setState({ age: person.age + 1 })}>
    Click me
  	</button>
  </div>
  )
}

useEffect

effect hook
从 React 组件获取数据、订阅或手动更改 DOM。我们称这些手术为“side effect”。

它的作用与 React 类中的componentDidMount、componentDidUpdate、componentWillUnmount相同, 是它们的一个合集。当你调用 useEffect 的时候,默认的会在每次更新之后调用 effect,包括第一次 render

React 组件中有两种常见的副作用: 不需要清理的副作用和需要清理的副作用。

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

function Example() {
  const [count, setCount] = useState(0);
  // 默认情况下在每次 render 完成后都会调用,包括第一次挂载和更新,并且根据 javascript 机制,每一次都是不同的 effect 函数。effect 会延迟到浏览器绘制完成后再执行。
  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    document.title = `You clicked ${count} times`;
    return () => {
		// 如果我们返回一个函数,会在 每次 render 和 unmount 的时候执行,我们可以在这个函数里面执行解绑逻辑。注意这里不止是在 unmount 执行。
	}
	// 可以声明多个 effect, 会按照定义顺序调用,这允许我们将代码分割到不同的函数中,而不是全部放到一个生命周期里面。
	useEffect(() => {
    	// featch data
  	});
	useEffect(() => {
    	// featch data
  	}, [count/* 这里作为第二个参数,是为了性能优化,为了避免每一次 re-render 都执行effect, 可以提供一个数组,里面的数据如果前后 render 没有改变,那么就会自动跳过这个 effect, 如果为 [], 那么只会在 mount and unmount 阶段执行, 并且在此 effect 中, props 或者 states 在其中一直都是最初的值。*/]);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

rules of hooks

1.总是在function component 顶部调用 hooks, 不要在循环、条件或嵌套函数中调用钩子。
2. 只在 function components. 中调用 hooks
3. hooks 每次 render 调用的时候,会对应到上次调用的顺序,如果放到条件语句中,如某一次不执行,会打乱原先的顺序,使得后面一个 hooks 对应到当前的 hooks。

customs hooks

自定义 hooks 是指我们定义一个 function 名字以 use 开头, 并且将一些公用逻辑放到该方法中,调用一些 React 定义的 hooks 。类似于高阶组件和 render props

需要注意的时候, customs hooks 复用的是 logic ,每次你使用它的时候,state、effecthooks 都是全新的。

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

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

useContext

// 一般来说 MyContext 需要公用,可以定义到一个文件中,然后再需要用到 useContext 的地方引入,该 context
const MyContext = React.createContext()
// 会向上查找使用该 context.provider 提供值的地方,并返回该值。只要该值发生改变,那么会触发使用下面这行代码的组件的rerender
const value = useContext(MyContext);

userReducer

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, init/*如果穿了这个方法,那么初始值会变为 init(initialArg) */);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}

useCallback

返回一个 callback

// 只有当数组中的依赖发生改变了之后 memoizedCallback 才会发生改变。所有 callback 内部引用到的变量,都需要出现在后面的数组中。
const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

usememo

返回一个 value,类似于 vue 的计算属性。

// 如果后面的数组的值为 [] 或者没有指定,那么每次 render 的时候都会计算。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useRef

const refContainer/*refContainer.current等于initalValue*/ = useRef(initialValue);

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

你可能感兴趣的:(react)