javascript Invariant Violation:Hooks 只能在函数组件内部调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/53612613/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:15:09  来源:igfitidea点击:

Invariant Violation: Hooks can only be called inside the body of a function component

javascriptreactjsreact-hooks

提问by intercoder

TL;DR:I'm trying to use the new react-hooksapi, but I keep getting an Invariant Violation error when calling the setStatehook, but it keeps failing.

TL;DR:我正在尝试使用新的react-hooksapi,但在调用setState钩子时我不断收到不变违规错误,但它一直失败。

import React, { useState } from 'react';

// type State = {
//   heading: string;
// }

const Text = () => {
  const initialState = 'Heading'.toUpperCase();

  const [heading, setHeading] = useState(initialState);

  return (
    <header>
      <h1>
        {setHeading('Brussels')};
        {heading}
      </h1>
    </header>
  );
};

export default Text;

采纳答案by jShubh

Calling setHeading("Brussel") will cause re rendering again and again which in turns result in an infinite loop, to prevent that you need an event to change the header from "Heading" to "Brussels". Below code might help you

调用 setHeading("Brussel") 将导致一次又一次的重新渲染,从而导致无限循环,以防止您需要一个事件将标题从“Heading”更改为“Brussels”。下面的代码可能对你有帮助

const Text = () => {
const initialState= 'Heading'.toUpperCase();
const [heading, setHeading] = useState(initialState);  
return (
 <header>
    <h1>
    {heading}
    <button onClick= {() =>{setHeading("Brussel")}}>ChangeName</button>
    </h1>
    </header>
);
};

回答by Yangshun Tay

If you think back in the class component version, your code is calling this.setStatein the render()which will trigger another render, and call this.setStateagain, and the cycle repeats, and you'll get the error:

如果您回想一下类组件版本,您的代码正在调用this.setStaterender()这将触发另一个渲染,然后this.setState再次调用,循环重复,您将收到错误:

Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

未捕获的错误:重新渲染过多。React 限制渲染次数以防止无限循环。

You wouldn't call this.setStatedirectly in your render method and neither should you do that using hooks.

您不会this.setState直接在渲染方法中调用,也不应该使用钩子来调用。

It's unclear what you're trying to achieve here, but I think what you want is to set the name only once, which you would do in componentDidMount, and you can use the useEffecthook to achieve that.

目前还不清楚你在这里想要实现什么,但我认为你想要的是只设置一次名称,你会在 中做componentDidMount,你可以使用useEffect钩子来实现这一点。

Or if you want "Brussels" to be the initial state, pass it as the value into useState().

或者,如果您希望“布鲁塞尔”成为初始状态,请将其作为值传递给useState().

const {useState, useEffect} = React;

const Text = () => {
  const initialState = 'Heading'.toUpperCase();
  const [heading, setHeading] = useState(initialState);
  useEffect(() => {
    setHeading('Brussels');
  }, []); // Pass in empty array to simulate componentDidMount.
  
  return (
    <header>
      <h1>
        {heading}
      </h1>
    </header>
  );
};

ReactDOM.render(<Text />, document.querySelector('#app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>