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>
        )
    }
}

image.png

在不停的点击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 属性的访问都会获取到最新的值

image.png

看下函数式组件

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'
        />
      </>
    );
  }

image.png

先点击 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'
      />
    </>
  );
}
image.png

React .forwardRef
React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特别有用:

React.forwardRef 接受渲染函数作为参数。React 将使用 propsref 作为参数来调用此函数。此函数应返回 React 节点。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容

  • 今年都过了四分之一,才鼓起勇气把它画出来。
    YOYO成长记阅读 199评论 0 1
  • 白履长裙靓丽衫 秀发披肩倚墙边 竹林青砖深幽处 玉女穿越至庄园 注: 四川大邑刘氏庄园
    琮淯阅读 460评论 6 14
  • *有人说:在16岁前一定要伤心彻骨一次;然后在17岁卯足了劲为梦想拼搏一次。因为只有伤心和挫折能让人体味到生命的冷...
    秦欢喜阅读 1,606评论 26 22
  • 时间的脚步越来越匆匆,刚看过旭日东升,转眼已是满天繁星。 生活中的苦与乐,悲与痛都已不太重。时光太过匆匆,光荫无改...
    初音未来_b9c2阅读 172评论 2 1