React Hooks — The Ins and Outs

栏目: IT技术 · 发布时间: 5年前

内容简介:E.g.There are a few drawbacks with HOC.

React Hooks — The Ins and Outs

Hooks are functions that let you “hook into” React state and lifecycle features from function components.

React Hooks — The Ins and Outs

Why hooks

How did we reuse stateful logic — HOC

E.g.

import { withRouter } from "react-router-dom";
import { Form } from 'antd';function A(props) {
  const {
    match: { params },
    history,
    form
  } = props;  return <div> test </div>;
}export default withRouter(Form.create()(A))

There are a few drawbacks with HOC.

  • wrapper hell of components. HOC actually returns a new component that wraps the original component.
  • unclear dependencies: from the view of Component A , we have no way to clearly know this.props.form is from Form.create HOC, and this.props.history is from withRouter HOC
  • naming conflicts: imagine that Form.create and withRouter both inject a prop with the same name, which can easily happen as they are two separate HOCs that are properly maintained by two teams

How can we improve with Hooks

import { useHistory } from "react-router-dom";
import { Form } from 'antd';export default function A(props) {
  const [form] = Form.useForm();
  const history = useHistory();  return <div> test </div>;
}
  • no wrapper any more as they are all at the same level
  • clear dependencies as they are from separate hooks call: form from useForm and history from useHistory
  • no naming conflicts as they are from separate hooks and you can rename hooks return values

Hooks in practice

To implement a controlled Input element with reset functionality, we can do it this way :

import React, { useState } from "react";
import { Input, Button } from 'antd';export default function App() {
  const initialValue = 'please enter something';
  const [inputValue, setInputValue] = useState(initialValue);  return (
    <div className="App">
        // note the value is from e.target
      <Input value={inputValue} onChange={e => setInputValue(e.target.value)}/>
      <Button onClick={() => setInputValue(initialValue)}> Reset </Button>
    </div>
  );
}

There are a couple of stateful logic that we can abstract and resue.

  • value fetch — e.target.value
  • reset logic — reset to initial value

custom hook — useEventTarget

import { useState, useCallback } from "react";export default function useEventTarget(initialValue = "") {
  const [value, setValue] = useState(initialValue);
  const onChange = useCallback(e => setValue(e.target.value), []); // reusable value fetch logic
  const reset = useCallback(() => setValue(initialValue), [initialValue]); // resuable reset logic  return {
    value,
    onChange,
    reset
  };
}

The above example can then be refactored with custom useEventTarget hook:

import React from "react";
import { Input, Button } from "antd";
import useEventTarget from "./useEventTarget";export default function App() {
  const { value, onChange, reset } = useEventTarget("please enter something");  return (
    <div className="App">
      <Input value={value} onChange={onChange} />
      <Button onClick={reset}> Reset </Button>
    </div>
  );
}

Mental overhead

Hooks is NOT a substitute for class lifecycles though useEffect can simulate what lifecycles do. Hooks facilitates reusing stateful logic but it comes with costs.

Assume that I need a page that display count which is from zero and increment by one per second.

import React, { useState, useEffect } from 'react';export default function SetInterval() {
  const [ count, setCount ] = useState(0);  useEffect(() => {
    const interval = setInterval(() => {
      console.log("interval count", count); // count is always 0
      setCount(count + 1);
    }, 1000);
    return () => {
      clearInterval(interval)
    }
  }, []);  return <div> normal count is { count } </div>;
}

With the code above , the count on the page will stay on 1. This is due to the fact that useEffect call only runs on mount (as useEffect dependency is set to [] on line 14) and the count value at that point is 0 (i.e the initial value we set with useState call on line 4). Each time the interval function is called, the count value will always be 0 as it’s a closure variable. Therefore, setCount(count + 1) will be setCount(1).

Solution 1 — useEffect dependencies

Specify the dependencies if your useEffect depends on outer variables

import React, { useState, useEffect } from "react";export default function SetInterval() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    const interval = setInterval(() => {
      console.log('interval count', count); // increment by one per run
      setCount(count + 1);
    }, 1000);    return () => {
      // each time count value changes (i.e per second, clear the interval and init one with new count value
      console.log('interval clear', count); 
      clearInterval(interval);
    }
  }, [count]);  return <div> dep count is {count} </div>;
}

Solution 2 — use state callback

import React, { useState, useEffect } from "react";export default function SetInterval() {
  const [count, setCount] = useState(0);  useEffect(() => {
    const interval = setInterval(() => {
      // it doesnt matter what count was, it tells React to increment by one with previous value
      setCount(a => a + 1);
    }, 1000);    return () => {
      clearInterval(interval);
    };
  }, []);  return <div> prev normal count is {count} </div>;
}

Solution 3 — useRef

import React, { useRef, useState, useEffect } from "react";export default function SetInterval() {
  const [count, setCount] = useState(0);
  const ref = useRef();
  ref.current = count;  useEffect(() => {
    const interval = setInterval(() => {
      console.log("interval count", ref.current);
      setCount(ref.current + 1);
    }, 1000);    return () => {
      clearInterval(interval);
    };
  }, []);  return <div> ref count is {count} </div>;
}

Notice

  • If you want to follow the latest news/articles for the series of my blogs, Please 「Watch」 to Subscribe.

以上所述就是小编给大家介绍的《React Hooks — The Ins and Outs》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C#入门经典

C#入门经典

[美] Karli Watson、Christian Nagel / 齐立波、黄静 / 清华大学出版社 / 2008-12 / 118.00元

这是一本成就无数C#程序员的经典名著,厚而不“重”,可帮助您轻松掌握C#的各种编程知识,为您的职业生涯打下坚实的基础,《C#入门经典》自第1版出版以来,全球销量已经达数万册,在中国也有近8万册的销量,已经成为广大初级C#程序员首选的入门教程,也是目前国内市场上最畅销的C#专业店销书,曾两次被CSDN、《程序员》等机构和读者评选为“最受读者喜爱的十大技术开发类图书”!第4版面向C#2008和.NET......一起来看看 《C#入门经典》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具