简体   繁体   English

react hooks与react class性能对比

[英]Performance comparison between react hooks and react class

I am trying to learn react hooks.我正在尝试学习反应钩子。 I need help in understanding does react functions always reset hook state every time it renders.我需要帮助来理解反应函数是否总是在每次呈现时重置钩子 state。

Here is a small example of scroll where I am trying to fix the header这是我试图修复 header 的滚动的一个小例子

class Header extends Component {


    constructor(props) {
        super(props);
        console.log("Constructor")
        this.state = {fixed: false};
    }


    handleScroll = () => {
        console.log(window.scrollY);
        console.log(this.state.fixed);
        if (window.scrollY >= 25 && !this.state.fixed) {
            this.setState({
                fixed: true
            });
        } else if(window.scrollY < 25 && this.state.fixed){
            this.setState({
                fixed: false
            });
        }
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        console.log("updated ");
    }

    componentDidMount() {
        console.log("added");
        window.addEventListener('scroll', this.handleScroll);
    }

    componentWillUnmount() {
        console.log("removed");
        window.removeEventListener('scroll', this.handleScroll);
    }

    render() {
        return (
            <div></div>
        );
   }
}

Output: Output:

Header.js:26 Constructor
Header.js:51 added
Header.js:32 1
Header.js:33 false
Header.js:32 2
Header.js:33 false
Header.js:32 5
Header.js:33 false
Header.js:32 9
Header.js:33 false
Header.js:32 15
Header.js:33 false
Header.js:32 20
Header.js:33 false
Header.js:32 26
Header.js:33 false
Header.js:47 updated 
Header.js:32 31
Header.js:33 true
Header.js:32 35
Header.js:33 true
Header.js:32 38
Header.js:33 true
Header.js:32 40
Header.js:33 true
Header.js:32 39
Header.js:33 true
Header.js:32 38
Header.js:33 true
Header.js:32 35
Header.js:33 true
Header.js:32 31
Header.js:33 true
Header.js:32 25
Header.js:33 true
Header.js:32 20
Header.js:33 true
Header.js:47 updated 
Header.js:32 9
Header.js:33 false
Header.js:32 5
Header.js:33 false
Header.js:32 2
Header.js:33 false
Header.js:32 0
Header.js:33 false

It works fine.它工作正常。

Now with react hooks same logic.现在使用 React Hooks 相同的逻辑。 I am just trying to look for the behavior of FixedHeader state.我只是想寻找 FixedHeader state 的行为。

const Header = props => {

    console.log("rendering");
    const [FixedHeader, setFixedHeader] = useState(false);

    useEffect(() => {
        document.addEventListener("scroll", () => {
            console.log(window.scrollY);
            console.log(FixedHeader);
            if (window.scrollY >= 30) {
                setFixedHeader(true);
            } else {
                setFixedHeader(false);
            }
        })
    }, []);


    return (
        <div></div>
   );
}

Output: Output:

Header.js:23 rendering
Header.js:28 1
Header.js:29 false
Header.js:28 2
Header.js:29 false
Header.js:28 5
Header.js:29 false
Header.js:28 9
Header.js:29 false
Header.js:28 15
Header.js:29 false
Header.js:28 20
Header.js:29 false
Header.js:28 26
Header.js:29 false
Header.js:28 31
Header.js:29 false
Header.js:23 rendering
Header.js:28 35
Header.js:29 false
Header.js:23 rendering
Header.js:28 38
Header.js:29 false
Header.js:28 40
Header.js:29 false
Header.js:28 39
Header.js:29 false
Header.js:28 38
Header.js:29 false
Header.js:28 35
Header.js:29 false
Header.js:28 31
Header.js:29 false
Header.js:28 25
Header.js:29 false
Header.js:23 rendering
Header.js:28 20
Header.js:29 false
Header.js:23 rendering
Header.js:28 14
Header.js:29 false
Header.js:28 9
Header.js:29 false
Header.js:28 5
Header.js:29 false
Header.js:28 2
Header.js:29 false
Header.js:28 0
Header.js:29 false

I can't understand this behavior why rendering is called twice, and FixedHeader is false even when scroll is >= 30.我不明白为什么渲染被调用两次,即使滚动 >= 30,FixedHeader 也是假的。

I am new to js so I think this is the way function work rendering is there 2 times because function got called twice but why twice, and each time function is called all the states need to be set again doesn't it going to impact the performance (I may be wrong).我是 js 的新手,所以我认为这是 function 工作渲染的方式有 2 次,因为 function 被调用了两次,但为什么调用了两次,每次调用 function 时,所有状态都需要重新设置,这不会影响性能(我可能是错的)。

Note: I have not added html part it is simple header where I am adding class "fixed-top" based on the boolean variable.注意:我没有添加 html 部分它很简单 header 我在其中添加 class 基于 boolean 变量的“固定顶部”。

I can't understand this behavior why rendering is called twice, and FixedHeader is false even when scroll is >= 30.我不明白为什么渲染被调用两次,即使滚动 >= 30,FixedHeader 也是假的。

I guess it is because of closure, the function remember FixedHeader value, which it had in a moment, function was created... you can create some object outside component and write FixedHeader to its property if you really need to see value inside your scroll event callback我想这是因为关闭,function 记住了 FixedHeader 值,它在一瞬间创建了 function ...如果您真的需要在滚动中查看值,您可以在组件外部创建一些 object 并将 FixedHeader 写入其属性事件回调

const holder = {}
const Header = props => {
    const [FixedHeader, setFixedHeader] = useState('false');
    holder.value = FixedHeader

    const handleScroll = function () {
      console.log(window.scrollY)
      console.log(holder.value)
      if (window.scrollY >= 30) {
        setFixedHeader('true');
      } else {
        setFixedHeader('false');
      }
    }

    useEffect(() => {
        document.addEventListener("scroll", handleScroll)
        return () => window.removeEventListener('scroll', handleScroll);
    }, []);



    return (

but because of react does not rerender immidiately sometimes value will not be right但由于 React 不会立即重新渲染,所以有时值会不正确

The reason "rendering" is displayed twice is because you are using different conditions. “正在渲染”显示两次的原因是您使用的条件不同。

For the class component you use:对于您使用的 class 组件:

if (window.scrollY >= 25 && !this.state.fixed) {
    // ...
} else if (window.scrollY < 25 && this.state.fixed) {
    // ...
}

While the function component uses:而 function 组件使用:

if (window.scrollY >= 30) {
    // ...
} else {
    // ...
}

To fix this issue you need to add the check the current state.要解决此问题,您需要添加检查当前 state。

However like you've already noticed checking FixedHeader value will always result in the same value (it is not getting updated).但是,就像您已经注意到的那样,检查FixedHeader值将始终产生相同的值(它不会更新)。 So we need to tackle that problem first.所以我们需要首先解决这个问题。

The problem is that setFixedHeader doesn't update the FixedHeader in the current context.问题是setFixedHeader不会更新当前上下文中的FixedHeader It tells React to re-render using the passed value as the new FixedHeader on the next Header call, but FixedHeader in the current context is never changed.它告诉 React 在下一次Header调用时使用传递的值作为新的FixedHeader重新渲染,但当前上下文中的FixedHeader永远不会改变。

useEffect allows you to return a function that handles clean-up. useEffect允许您返回处理清理的 function。 This function runs if the component unmounts, or before the next call of useEffect (when the dependency list has changed).这个 function 在组件卸载时运行,或者在下一次调用useEffect之前运行(当依赖列表发生变化时)。 Adding FixedHeader to the dependency list will remove the previous scroll event handler (using the returned clean-up function) and adds a new scroll event handler using the new FixedHeader value when the FixedHeader value changes.FixedHeader添加到依赖列表将删除之前的滚动事件处理程序(使用返回的清理函数)并在FixedHeader值更改时使用新的FixedHeader值添加新的滚动事件处理程序。

 const {useEffect, useState} = React; const Header = props => { console.log("rendering"); const [fixed, setFixed] = useState(false); useEffect(() => { const handleScroll = () => { console.log(window.scrollY); console.log(fixed); if (window.scrollY >= 30 &&;fixed) { setFixed(true). } else if (window;scrollY < 30 && fixed) { setFixed(false); } }. document,addEventListener("scroll"; handleScroll). return () => document,removeEventListener("scroll"; handleScroll), }; [fixed]); return null. } ReactDOM,render(<Header />. document;querySelector("#header-container"));
 body { height: 1000px; }
 <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script> <div id="header-container"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM