关注互联网应用及运维技术的个人博客

react函数编程Hook笔记

hook在不编写class的情况下使用state,目的就是解决class中生命周期函数经常包含的不相关逻辑,相关逻辑有分离到不同方法中等这类问题

useState

定义一个“state变量”,

import React,{useState} from "react";
const [num,setNum]  =useState(0) 

与在this.state中定义的变量一样

useEffect

Effect Hook在函数组件中执行副作用操作

副作用:订阅、手动更改组件等操作。Effect Hook是componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合

useEffect在组件渲染后执行一些副作用操作,有需要删除的副作用,则返回一个函数;没有则不需要返回

如:

    useEffect(() => {
        document.title = `点击次数:${num}`
    })
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

同样是在组件渲染后执行一些副作用操作,class组件则需要拆分,如:

class FriendStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOnline: null };
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  handleStatusChange(status) {
    this.setState({
      isOnline: status.isOnline
    });
  }

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

性能优化

useEffect,只需要传递数组作为第二个参数即可。

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新

Hook 使用条件:

  1. 只在最顶层使用Hook,不能在循环,条件或者嵌套函数中使用Hook
  2. 不能在普通JavaScript函数中使用Hook函数

基础Hook:

  1. useState
const [num,setNum] = useState(0);

返回一个state,更新state的函数

  1. useEffect
useEffect(doUpdate)

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

接受一个包含命令式、副作用操作的函数(代码)

  1. useContext
const value = useContext(MyContext)

额外的Hook

  1. useReducer

useState的替代方案,当state逻辑很复杂并且包含多个字值的时候,useReducer比useState更适合。

function init(initialCount) {
  return { count: initialCount };
}
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 };
    case 'reset':
      return init(action.payload);
    default:
      throw new Error();
  }
}
function Counter({ initialCount }) {
  // const [state, dispatch] = useReducer(reducer, 1, init);
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button
        onClick={() => dispatch({ type: 'reset', payload: initialCount })}>
        Reset
      </button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </>
  );
}
  1. useCallback

参数为内联回调函数和依赖项数组,在某一个依赖项发生改变时,回调函数才会更新。返回memoized回调函数

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

 useCallback(fn,deps) <=> useMemo(()=>fn,deps)
  1. useMemo

返回一个memoized值,以“创建”函数和依赖项数组作为参数,某一个依赖项发生变化时,重新计算memoized值,没有传入依赖项时,useMemo在每一次渲染都会计算memoized的值。

const memoizedValue =  useMemo(()=>fn(a,b),[a,b])
  1. Ref
const refContainer = useRef(initialValue);

返回一个可变的ref对象

  1. useImperativeHandle

useImperativeHandle 应当与 forwardRef 一起使用

useImperativeHandle(ref, createHandle, [deps])

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
  1. useLayoutEffect

在所有的DOM变更之后同步调用effect,读取DOM布局并同步触发重渲染。


  1. useDebugValue

可用于在 React 开发者工具中显示自定义 hook 的标签

赞(0)
未经允许不得转载:飞天狒狒 » react函数编程Hook笔记

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址