React Hooks -useState/useEffect/useRef详解(1)

3,179 阅读3分钟

这是我参与更文挑战的第21天,活动详情查看: 更文挑战

1, useState

1, 用法

  const [state, setState] = useState(initialState)

2, 说明

useState返回两个值,一个是带有初始值的变量,一个是更新这个变量的函数

在第一次渲染的时候,返回的状态state与传入的第一个参数值相同。

setState函数用于更新state, 当它接收一个新的 state 值的时候,会将组件的一次重新渲染加入队列,

setState(newState)

切记: setState执行渲染,如果是对象,里面的值必须是一个新对象

有一种错误的写法:

  const [obj, setObj] = useState({name: 'zlm'})
​
  <button onClick={()=> (
          setObj(Object.assign(obj, {name: 'JamieDawn'}))
   )}>修改</button>

Object.assgin(obj, {name: "JamieDawn"}) 只是修改了对象里面的值,并不是一个新对象,所以点击修改没有任何变化

3, 举例

import './App.css';
import React , { useState } from 'react'function App() {
  const [count, setCount] = useState(0)
  const [obj, setObj] = useState({name: 'zlm'})
  const [arr, setArr] = useState([1,2,3])
  const [fun, setFun] = useState(()=> {return {age: 19};})
  return (
    <>
      <h2>{count}</h2>
      <button onClick={()=>(setCount(count + 1))}>修改-变量</button>
      <h2>{obj.name}</h2>
      <button onClick={()=> (
        setObj(Object.assign({},obj, {name: 'JamieDawn'}))
      )}>修改-对象</button>
      <h2>{arr}</h2>
      <button onClick={()=> (
        setArr(()=> {
          arr.push(4)
          return [...arr]
        })
      )}>修改-数组</button>
      <h2>{fun.age}</h2>
      <button onClick={()=>(
        setFun(()=> {
          return {age: 24}
        })
      )}>修改-函数</button>
    </>
  );
}
​
export default App;
​

2, useEffect

1, 用法

useEffect(didUpdate);

2, 说明

默认情况下,effect 将在每轮渲染结束后执行,但你可以选择让它 在只有某些值改变的时候 才执行。

使用 useEffect 完成副作用操作。赋值给 useEffect 的函数会在组件渲染到屏幕之后执行。你可以把 effect 看作从 React 的纯函数式世界通往命令式世界的逃生通道。

通常,组件卸载时需要清除 effect 创建的诸如订阅或计时器 ID 等资源。要实现这一点,useEffect 函数需返回一个清除函数

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

3, 特点

  • 执行时机, componentDidMount, componentDidUpdate, componentWillUnmount
  • 副作用,包括DOM操作,数据请求,组件更新
  • useEffect为什么在组件函数内部执行? 可以获取到props和state, 采用闭包的形式
  • 无阻塞更新
  • useEffect(回调函数,数组)
  • 多个useEffect()

注意:

(1) useEffect, 默认第二个参数不写,就是监听所有的state, 只要有state发生变化,就会触发执行

(2) useEffect 第二个参数给个空数组,初始化页面挂载之后,只执行一次

import './App.css';
import React , { useState, useEffect } from 'react'function App() {
  const [count, setCount] = useState(0)
  const [age, setAge] = useState(20)
​
  useEffect(() => {
      console.log('我执行了count=', count)
      return () => {
          console.log('componentWillUnmount')
      }
  }, [count])
  return (
    <>
     <h2>effect</h2>
     <h2>{count}</h2>
     <button onClick={onClick=> {setAge(age + 1)}}>改变-age</button>
     <button onClick={onClick=> {setCount(count + 1)}}>改变-count</button>
​
     </>
  );
}
​
export default App;
​

3, useRef

1, 用法

const inputEL = useRef(null)

2, 说明 useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。

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

3, 作用

  • useRef 用来获取DOM元素
  • useRef 用来保存变量

4, 举例子

import './App.css';
import React , { useState, useRef } from 'react'function App() {
  const inputEl = useRef(null)
  const save = useRef({value: 123})
  
  return (
    <>
     <h2>useRef</h2>
     <input type='text' inputRef={inputEl}/>
     <button onClick={()=> {
         save.current.value = inputEl.current.value
         console.log(save)
     }}>保存-age</button>
     </>
  );
}
​
export default App;
​