无限循环 React 钩子 [英] Infinite loop React hooks

查看:23
本文介绍了无限循环 React 钩子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么我会陷入无限循环useClick 我看到我使用 setVal 更改了 useEffect 内的状态值,但 useEffect 应该只对第二个参数中指定的 onClick 起作用.我认为这是因为我传递的参数 onClick 已被记忆但未调用回调(我使用 console.log('go set')

检查了这一点

function useClick(onClick, setVal, val) {React.useEffect(() => {console.log('点击');setVal(val + 1);}, [onClick]);}const Home = () =>{const [val, setVal] = React.useState(0);const incrementOnClick = React.useCallback(() => {console.log('去设置');setVal(val + 1);} , [setVal, val]);useClick(incrementOnClick, setVal, val);返回 

<div>{val}</div><button onClick={incrementOnClick}>点击我</button>

}

解决方案

valsetVal 将在每次渲染时发生变化,进而导致 incrementOnClick 成为一个新的函数引用,你的 useClick 效果会一直被调用.

您可以改为提供一个函数作为 setVal 的第一个参数.此函数获取当前 val 作为参数并返回新值.这样 incrementOnClick 将始终是相同的功能.

const { useEffect, useState, useCallback } = React;函数 useClick(onClick, setVal, val) {useEffect(() => {console.log("点击");setVal(val + 1);}, [onClick]);}const Home = () =>{const [val, setVal] = useState(0);const incrementOnClick = useCallback(() => {console.log("去设置");setVal(val => val + 1);}, []);useClick(incrementOnClick, setVal, val);返回 (<div><div>{val}</div><button onClick={incrementOnClick}>点击我</button>

);};ReactDOM.render(, document.getElementById("root"));

<script src="https://unpkg.com/react@16/umd/react.development.js"><;/脚本><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><div id="root"></div>

上面的代码展示了如何摆脱无限循环并且对实验很有价值,但大部分都不是必需的.您可以改为编写相同的功能:

const { useState } = React;const Home = () =>{const [val, setVal] = useState(1);返回 (<div><div>{val}</div><button onClick={() =>setVal(val + 1)}>点击我</button>

);};ReactDOM.render(, document.getElementById("root"));

<script src="https://unpkg.com/react@16/umd/react.development.js"><;/脚本><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><div id="root"></div>

I don't understand why I'm getting infinite loop in useClick I see that I change state value inside useEffect using setVal but useEffect should work only on onClick as specified in second param. I thought that it is because the param onClick i pass is memoized but the callback is not called(i checked that using console.log('go set')

function useClick(onClick, setVal, val) {
  React.useEffect(() => {
    console.log('Click');
    setVal(val + 1);
  }, [onClick]);
}

const Home = () => {
  const [val, setVal] = React.useState(0);
  const incrementOnClick = React.useCallback(() => {
    console.log('go set');
    setVal(val + 1);
  } , [setVal, val]);
  useClick(incrementOnClick, setVal, val);
  return <div>
    <div>{val}</div>
    <button onClick={incrementOnClick}>Click me</button>
 </div>
}

解决方案

val and setVal will change on every render, which in turn will cause incrementOnClick to become a new function reference, and your useClick effect will always be invoked.

You could instead give a function as first argument to setVal. This function gets the current val as argument and returns the new value. This way incrementOnClick will always be the same function.

const { useEffect, useState, useCallback } = React;

function useClick(onClick, setVal, val) {
  useEffect(() => {
    console.log("Click");
    setVal(val + 1);
  }, [onClick]);
}

const Home = () => {
  const [val, setVal] = useState(0);
  const incrementOnClick = useCallback(() => {
    console.log("go set");
    setVal(val => val + 1);
  }, []);

  useClick(incrementOnClick, setVal, val);

  return (
    <div>
      <div>{val}</div>
      <button onClick={incrementOnClick}>Click me</button>
    </div>
  );
};

ReactDOM.render(<Home />, document.getElementById("root"));

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

The code above shows how you could get away from the infinite loop and could be valuable for experimentation, but most of it isn't necessary. You could write the same functionality like this instead:

const { useState } = React;

const Home = () => {
  const [val, setVal] = useState(1);
  
  return (
    <div>
      <div>{val}</div>
      <button onClick={() => setVal(val + 1)}>Click me</button>
    </div>
  );
};

ReactDOM.render(<Home />, document.getElementById("root"));

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

这篇关于无限循环 React 钩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆