Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react函数编程Hook #6

Open
duxinyues opened this issue Aug 9, 2020 · 0 comments
Open

react函数编程Hook #6

duxinyues opened this issue Aug 9, 2020 · 0 comments

Comments

@duxinyues
Copy link
Owner

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对象
5. 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 的标签

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant