react hooks

记录一下学习过程中的笔记,也便于自己查看
Hooks 能够在无需编写类的情况下使用状态和其他 React 特性 例如-组件的状态
你可以使用 Hook 从组件中提取状态逻辑,使得这些逻辑可以单独测试并复用。

什么是hook?

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。

useState Hook

useState用于管理页面中的状态,返回当前状态和改变当前状态的方法,可以说是最常用的hook。
场景 当你需要向函数式组件向其添加一些state,并对其进行管理

import React {useState} from 'react';
function example(){
    const [count, setCount] = useState(0);

    return (
        <div>
            <span>{count}</span>
            <button onClick={()=>setCount(count+1)>
        </div>
    )
}

以上例子引入useState用于管理组件的内部state
组件通过调用 useState Hook 声明了一个新的 state 变量。它返回一对值给到我们命名的变量上。我们把变量命名为 count,它存储的是点击次数。我们通过传入一个值 0 作为 useState 唯一的参数来将其初始化为 0。第二个返回的值是一个setState函数,这个函数可以更新 count 的值.

useEffect Hook

useEffect能够在组件中执行副作用
useEffect 的执行时机 在组件 mount 和 unmount 以及每次重新渲染的时候执行,也就是会在 componentDidMount、componentDidUpdate、componentWillUnmount 这三个时期执行。

effect分为需要清除的不用清除两种
清理函数(clean up)什么时候执行? 它会在前一次 effect执行后,下一次 effect 将要执行前,以及 Unmount 时期执行
使用场景
无需清除的Effect
*发送网络请求
*监听页面大小变化

function getSize() {
  return {
    innerHeight: window.innerHeight,
    innerWidth: window.innerWidth,
    outerHeight: window.outerHeight,
    outerWidth: window.outerWidth
  };
}
 
function useWindowSize() {
  let [windowSize, setWindowSize] = useState(getSize());
 
  function handleResize() {
    setWindowSize(getSize());
  }
 
  useEffect(() => {
    window.addEventListener("resize", handleResize);
    return () => {
      window.removeEventListener("resize", handleResize);
    };
  }, []);
 
  return windowSize;
}
const windowSize = useWindowSize();
return <div>页面高度:{windowSize.innerWidth}</div>;

需要清除的Effect
*订阅外部数据源

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // 清除订阅
    subscription.unsubscribe();
  };
});

其中useEffect中返回了一个函数,用于清除Effect。
React会在组件卸载的时候执行清除操作。

useEffect 会在每次渲染结束后执行,但也可以选择让它在只有某些值改变的时候才执行。下述例子在props.source改变时才会执行。

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

UseContext

用来处理多层级传递数据的方式。在一些组件中,跨层级祖先组件想要给孙子组件传递数据的时候,除了将props一层层往下传到孙子组件的方法之外,还可以使用useContext。

利用React.createContext创建一个context对象

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
}
const ThemeContext = React.createContext(themes.light);

使用Context.Provider提供了一个Context对象,这个对象可以被所有子组件共享

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

子组件利用useContext来获取Context对象,并且获取到它的值。

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}

useReducer

useState能够管理组件的一些状态,但是当state逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 的情况时利用useReducer更为适用。
基本用法

const [state, dispatch] = useReducer(reducer, initialArg, init);

其中useReducer的参数为一个reducer函数和一个状态的初始值,并且返回一个数组。数组的第一个成员是状态的当前值,第二个成员是发送 action 的dispatch函数。
其中reducer函数的参数为当前的状态和action.

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);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

以上例子可以看到dispatch 的参数是 reducer 的 action,reducer 函数根据传入的 action 执行某些逻辑,最后返回的就是新状态。

useRef

应用场景
1、保存可变的值
2、访问DOM

场景1、保存可变的值
useRef接收一个参数作为初始值,并返回一个引用,该引用有一个特殊的属性current.
利用reference.current 能够获取到引用的值,
reference.current = newValue 能够更新reference的值。

import { useRef } from 'react';
function MyComponent() {
  const reference = useRef(initialValue);
  const someHandler = () => {
    // Access reference value:
    const value = reference.current;
    // Update reference value:
    reference.current = newValue;
  };
}

值得注意的是,在组件重新渲染后reference.current的值不会改变 ;
并且当 reference.current的值改变后不会触发组件的更新。

场景2、访问dom 元素,可获取被标识元素的属性。

import { useRef, useEffect } from 'react';
function InputFocus() {
  const inputRef = useRef();
  useEffect(() => {
    inputRef.current.focus();
  }, []);
  return (
    <input 
      ref={inputRef} 
      type="text" 
    />
  );
}

自定义hook

将上述介绍的hooks封装起来可以变成一个自定义的钩子
所有的钩子都是为函数引入外部功能,所以 React 约定,钩子一律使用use前缀命名,便于识别。所以当你定义自己的hook时需要将钩子函数命名为usexxxx.

const usePerson = (personId) => {
  const [loading, setLoading] = useState(true);
  const [person, setPerson] = useState({});
  useEffect(() => {
    setLoading(true);
    fetch(`https://swapi.co/api/people/${personId}/`)
      .then(response => response.json())
      .then(data => {
        setPerson(data);
        setLoading(false);
      });
  }, [personId]);  
  return [loading, person];
};

其中usePerson就是自定义的一个hook。
在person组件使用usePerson。

const Person = ({ personId }) => {
  const [loading, person] = usePerson(personId);

  if (loading === true) {
    return <p>Loading ...</p>;
  }

  return (
    <div>
      <p>You're viewing: {person.name}</p>
      <p>Height: {person.height}</p>
      <p>Mass: {person.mass}</p>
    </div>
  );
};

###参考链接
https://dmitripavlutin.com/react-useref-guide/
https://www.geeksforgeeks.org/reactjs-usereducer-hook/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值