功能组件不断重复渲染

时间:2019-08-06 21:22:46

标签: javascript reactjs react-hooks

我的react函数组件会不断地重新渲染自身,直到浏览器崩溃为止。

我唯一能找到的解决方案是在useEffect()末尾输入带有常量的[]。

function getNestedObject(nestedObj, pathArr) {
  return pathArr.reduce(
    (obj, key) => (obj && obj[key] !== "undefined" ? obj[key] : undefined),
    nestedObj
  );
}

function Genres() {
  const [genreList, setgenreList] = useState(0);

  useEffect(() => {
    let results = "";
    axios({
      url: "https://api.themoviedb.org/3/genre/movie/list?",
      method: "GET",
      responseType: "json",
      params: {
        api_key: "00000000000",
        language: "en-US"
      }
    }).then(result => (results = result.data.genres));

    let a = [];
    for (let i = 0; i < 10; i++) {
      let name = getNestedObject(results, [i, "name"]);
      a.push(name);
    }
    setgenreList(a);
    console.log(genreList);
  }, [genreList]);
  return <div>test</div>;
}

我也尝试了不使用useEffect的情况,它给出了相同的循环结果。

我在渲染中放了<Genres />

3 个答案:

答案 0 :(得分:6)

发生这种情况是因为您在打电话

    setgenreList(a);

在useffect,genreList更改其状态,UseEffect再次运行

写作时

  useEffect(() => {}, [genreList])

然后每次调用它的设置器 setgenreList

时都会调用它

你可以写

useEffect(() => {
    //code here
    }, [])

答案 1 :(得分:1)

实际上,您每次都会生成一个空数组,并且每次都使用一个新生成的数组来更新状态,因此useEffect会无限循环(请检查[] === [])。另外,您在代码中还有一个明显的错误:状态更新根本不依赖于axios结果,因为您不必等待响应结果(在setgenreList(a)之后执行“ then”块)。在“然后”功能中使用状态更新。

答案 2 :(得分:1)

我想我会添加一个类似的实现的小答案,以及如何至少根据当前的实现(基于Rules of Hooks)处理条件

对于其中一个,您似乎完全按照文档进行操作,当调用useState时,会为其提供默认值,并将其设置为0,而应该将其设置为{空数组(因为之后要用它填充数组)

对于useEffect,您不需要将第二个参数作为一个空数组(尽管这表明效果永远不要重新运行),您也可以将其保留为空,但是可以验证数组是否已经存在值时,您可以进行网络调用(您使用,但为简单起见,我改用本地fetch

const { useState, useEffect } = React;

const container = document.querySelector('#container');

const BreedList = () => {
  const [breeds, setBreeds] = useState([]);
  
  useEffect( () => {
    if (!breeds.length) {
      fetch( 'https://dog.ceo/api/breeds/list/all' )
        .then( resp => resp.json() )
        .then( result => {
          setBreeds( Object.keys( result.message ) );
        } );
    }
  }, [breeds] );
  
  return (
    <div>
      <h1>Breeds</h1>
      { breeds.map( breed => <div key={ breed }>{ breed }</div> ) }
    </div>
  );
};

ReactDOM.render( <BreedList />, container );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="container"></div>