react Hook 一些用法

useState

import React, { useState } from "react";
function App() {
  const [obj, setObject] = useState({
    count: 0,
    name: "alife"
  });
  return (
    <div className="App">
      Count: {obj.count}
      <button onClick={() => setObject({ ...obj, count: obj.count + 1 })}>+</button>
      <button onClick={() => setObject({ ...obj, count: obj.count - 1 })}>-</button>
    </div>
  );

useEffect


import React, { useState, useEffect } from "react";
let timer = null;
function App() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = "componentDidMount" + count;
  },[count]);
 
  useEffect(() => {
    timer = setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);
    return () => {
      document.title = "componentWillUnmount";
      clearInterval(timer);
    };
  }, []);
  return (
    <div>
      Count: {count}
      <button onClick={() => clearInterval(timer)}>clear</button>
    </div>
  );
}

useContext 減少組件層級

const colorContext = React.createContext("gray");
function Bar() {
  const color = useContext(colorContext);
  return <div>{color}</div>;
}
function Foo() {
  return <Bar />;
}
function App() {
  return (
    <colorContext.Provider value={"red"}>
      <Foo />
    </colorContext.Provider>
  );
}

useMemo 先看一個例子

export default class a extends React.Component {
    state = {
        num: 1
    }
    handleClick = () => {
        const { num } = this.state;
        this.setState({
            num: num + 1
        })
    }
    handTestClick = () => {

    }
    renderTest = () => {
        console.log('函數組件渲染')
        return (
            <Text>
                function Children
             </Text>
        )
    }
    render() {
        const { num } = this.state;
        return (
            <View style={{ display: "flex", justifyContent: "center", alignItems: "center", flex: 1 }}>
                <TouchableOpacity style={{ color: "#333", fontSize: 20 }} onPress={this.handleClick}>
                    <Text>{num}</Text>
                </TouchableOpacity>
                {this.renderTest()}
                <Test onClick={this.handTestClick} />
            </View>
        )
    }
}


在不停的點擊handleClick的時候,函數式組件不停的渲染,如果這個函數式組件返回比較複雜的時候,會造成性能損耗,用useMemo 來返回一個記憶函數 同時你也可以根據第二個參數,第二個參數傳入一個數組,數組中的每一項一旦值或者引用發生改變,useMemo 就會重新返回一個新的記憶函數提供給後面進行渲染。

import React, {useMemo, useState, useCallback ,useEffect} from 'react';
import {
    Text,
    View,
    TouchableOpacity
} from 'react-native';
import Test from './components/Test'

export default () => {
    const [num, useNum] = useState(1)
    const handleClick = () => {
        useNum(num + 1)
    }
    const handTestClick = () => {

    }

    const renderTest = useMemo(() => {
        console.log('函數組件渲染')
        return (
            <Text>
                function Children
             </Text>
        )
    },[])

    return (
        <View style={{ display: "flex", justifyContent: "center", alignItems: "center", flex: 1 }}>
            <TouchableOpacity style={{ color: "#333", fontSize: 20 }} onPress={handleClick}>
                <Text>{num}</Text>
            </TouchableOpacity>
            {renderTest}
            <Test onClick={handTestClick} />
        </View>
    )

}

Capture Value 特性
看一個類組件

import React, { useEffect, useState } from 'react';
import {
  Button,
  TextInput
} from 'react-native';


export default class a extends React.Component {
  state={
    message:''
  }
  showMessage = () => {
    const { message } = this.state
    alert("You said: " + message);
  };
  handleMessageChange = e => {
    this.setState({
      message: e
    })
  };
  handleSendClick = () => {
 
    setTimeout(this.showMessage, 3000);
  };
  render() {
    const { message } = this.state;
    return (
      <>
        <TextInput style={{ height: 40, width: 200 }} value={message} onChangeText={this.handleMessageChange} />
        <Button
          onPress={this.handleSendClick}
          title='Send'
        />
      </>
    );
  }
}

先點擊Send 按鈕後,再次修改輸入框的值,3 秒後的輸出的結果是期望值,因爲這時候 message 是掛載在 this 變量上,它保留的是一個引用值,對 this 屬性的訪問都會獲取到最新的值

看下函數式組件

export default function(props) {

    const [message, setMessage] = useState('');

    const showMessage = () => {
      alert("You said: " + message);
    };

    const handleSendClick = () => {
      setTimeout(showMessage, 3000);
    };

    const handleMessageChange = e => {
      console.log(e)
      setMessage(e);
    };

    return (
      <>
        <TextInput style={{height:40,width:200}} value={message} onChangeText={handleMessageChange} />
        <Button
         onPress={handleSendClick}
         title='Send'
        />
      </>
    );
  }


先點擊 Send 按鈕後,再次修改輸入框的值,3 秒後的輸出依然是點擊前輸入框的值。這就是所謂的 capture value 的特性 useRef 創建一個引用,就可以有效規避 React Hooks 中 Capture Value 特性。
如何規避 React Hooks 中 Capture Value 特性 ?
使用 useRef 創建一個引用 只要將賦值與取值的對象變成 useRef,而不是 useState,就可以躲過 capture value 特性,在 3 秒後得到最新的值。


export default function (props) {
  const latestMessage = useRef();
  const [message, setMessage] = useState('');

  const showMessage = () => {
    console.log(latestMessage)
    const { props:{value} } = latestMessage.current
    alert("You said: " + value);
  };

  const handleSendClick = () => {
    setTimeout(showMessage, 3000);
  };

  const handleMessageChange = e => {
    console.log(e)
    setMessage(e);
  };

  return (
    <>
      <TextInput ref={latestMessage} style={{ height: 40, width: 200 }} value={message} onChangeText={handleMessageChange} />
      <Button
        onPress={handleSendClick}
        title='Send'
      />
    </>
  );
}

React .forwardRef
React.forwardRef 會創建一個React組件,這個組件能夠將其接受的 ref 屬性轉發到其組件樹下的另一個組件中。這種技術並不常見,但在以下兩種場景中特別有用:

React.forwardRef 接受渲染函數作爲參數。React 將使用 propsref 作爲參數來調用此函數。此函數應返回 React 節點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章