React Hooks

React Hooks

  • useState
  • useEffect
  • useRef
  • memo
  • useCallback
  • useMemo

useState

参数:初始state的值。支持传具体值或者函数。

返回值:一个数组,0:当前state的值;1:更新state的函数(类似于this.setState),支持传函数,函数的参数为当前的state值。

import React, { useState } from 'react';

function Example(props) {
  // 声明一个叫 “count” 的 state 变量。
  const [count, setCount] = useState(0); // 数组解构
  const [count, setCount] = useState(() => {
    return props.count || '0'
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useState可以多次使用

function ExampleWithManyStates() {
  // 声明多个 state 变量!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}

set函数用法

import React, { useState } from 'react';

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

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count => count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect

首次渲染完成,每次更新及组件卸载时会执行,相当于把生命周期componentDidMount, componentUpdate, componentWillUnmount合并成一个勾子了。

监听第二个参数[]的state的变化,执行第一个参数,如果第二个参数不传值,默认所有state更新时都会执行effect。

useEffect在第一个参数函数主体里return相当于componentWillUnmount。return必须是一个function。
如果effect返回一个函数,当组件卸载时会执行该函数,即useEffect返回的函数相当于unmount。

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

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

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

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

当第二个参数为空数组的时候对应didMount;
当第二个数组有值时,对应的state中的值变化时,执行effect;
useEffect也可以写多个,

function ExampleWithManyStates() {
  // 声明多个 state 变量!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');

  useEffect(() => {
    console.log(age)
  }, [age]) // 只有在age有变化时才执行effect
}

useRef

useRef返回一个可变的ref对象,获取最新的state,返回值是一个对象:{current: 当前变量的值}。
返回的ref对象在组件的整个生命周期内保持不变。

用法1:类似于refs的用法,命令式的访问子组件。

function TextInputWithFocusButton() {
  const inputEl = useRef(null); // {current: input元素}
  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    // 使输入框获得焦点
    inputEl.current.focus();
  }
  return (
    <div>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </div>
  )
}

用法2:获取最新的state

import React, { useEffect, useState, useRef } from "react";
function Demo(){
	const numRef = useRef();
	const [num, changeNum] = useState(1);
   function  submit(){
		console.log(`现在的数字是: ${numRef.current}`)
	}
	useEffect(() => {
	  numRef.current = num;
	});
}

memo

简单的子组件可以用memo包裹来节约计算性能,父组件重新render时,子组件不会跟着重新渲染;

memo的功能类似PureComponent。

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

const Img = (props) => {
  console.log('Img render');
  return <p>img component: {props.imageData}</p>;
};

const ImgMemo = memo(Img);

export default () => {
  const [count, setCount] = useState(1);
  const [imageData, setImageData] = useState('src1');
  const addCount = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p onClick={addCount}>click {count}</p>
      <ImgMemo imageData={imageData} />
    </div>
  );
};

useCallback

当父组件向子组件传递一个函数作为属性时,即使触发函数子组件没有变化时子组件也会重新渲染;

原因:向子组件传递一个非基本类型的函数作为属性时,父组件每次重新渲染,属性值都会被重新赋值,属性值发生变化,子组件就会重新渲染。

useCallback就是保证父组件在初始化时创建一个对象,当useCallback的依赖变量没有变化时,改对象就不会发生变化。

useCallback是在父组件传递函数作为属性给子组件的时候用的。

import React, { useState, memo, useCallback  } from 'react';

const Img = (props) => {
  console.log('Img render');
  return <p>img component: {props.imageData}</p>;
};

const ImgMemo = memo(Img);

export default () => {
  const [count, setCount] = useState(1);
  const [imageData, setImageData] = useState('src1');
  const addCount = () => {
    setCount(count + 1);
  };

  const onImgClick = useCallback(() => {
    setImageData('src2');
  }, []);

  return (
    <div>
      <p onClick={addCount}>click {count}</p>
      <ImgMemo imageData={imageData} onImgClick={onImgClick} />
    </div>
  );
};

useMemo

父组件向子组件传一个对象数据类型的属性时,如果在子组件中引用该对象属性的字段没有发生变化时,使用useMemo减少不必要的渲染。

当useMemo依赖的变量发生变化时才会重新渲染。

import React, { useState, memo, useMemo } from 'react';

const Img = (props) => {
  console.log('Img render');
  return <p>img component: {props.imageData.a}</p>;
};

const ImgMemo = memo(Img);

export default () => {
  const [count, setCount] = useState(1);
  const [imageData, setImageData] = useState({
    a: '1'
  });
  const addCount = () => {
    setCount(count + 1);
    setImageData({
      ...imageData,
      b: new Date()
    });
  };

  const imageDataMemo = useMemo(() => {
    return imageData
  }, [imageData.a])

  return (
    <div>
      <p onClick={addCount}>click {count}</p>
      <ImgMemo imageData={imageDataMemo} />
    </div>
  );
};
  • 函数名首字母一定要大写
  • 如果useEffect在第一个参数里存在定时器记得在return的时候清除掉,不清除掉会报错
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值