繁体   English   中英

React.js 无限重新渲染

[英]React.js infinite re-render

我的代码有问题。 我的 function “getNames” 可能会重新渲染一次,但我希望它渲染一次? 你有什么线索吗?

 import grounds from './../../UballersGroundsData.json'; export default function Groundlist() { function getNames(jsonObj){ for(let item in jsonObj){ console.log("item = " + item); for(let property in jsonObj[item] ){ console.log(jsonObj[item]); // if (property === "groundName"){ // console.log(jsonObj[item][property]); // } } } } return( <div> <h1>Hello world!</h1> <ul> {getNames(grounds)} </ul> </div> ) }

谢谢 !

您应该将 function 放在useEffect 挂钩中,然后将其设置为带有 useState 的state 挂钩 然后,map 为您的列表列出列表项(假设您从函数返回一个数组)。 如果你希望它只在第一次渲染时运行 getNames,你可以用一个空的依赖数组来设置 useEffect 钩子。 代码应如下所示:

import React, { useEffect, useState } from 'react'
import grounds  from './../../UballersGroundsData.json';

export default function Groundlist() {
    const [names, setNames] = useState([]) // Initial state with empty array

    useEffect(() => {
        function getNames(jsonObj){
            // your function logic here...       
        }
        const result = getNames(grounds) // Call your function
        setNames(result) // set it to names state hook
    }, []) // Empty array here means it will only use the useEffect on the first render.

return(
        <div>
            <h1>Hello world!</h1> 
            <ul>
                {Array.from(names).map(name =>  <li>{name}</li>)}
            </ul>

        </div>
    )
}

您可以使用useMemo反应挂钩来记忆返回的值,即由于其他 state、道具或上下文变量的变化而跳过不必要的/繁重的计算。

例子:

import { useMemo } from "react"

export default function Groundlist(props) {

  const grounds = props.data // if grounds is passed as props from Parent component

  const groundsMemo = useMemo(() => {
    // do all the heavy calculations here 
    // (e.g. do the work of getNames function)
    
    // and return some JSX or Array (data)

    // returned value will be memoized;
    // means it will be re-calculated only if "grounds" changes
    
    // Hence, no unnecessary calls to getNames (heavy calculations)

  }, [grounds])

  return (
    <div>
      {/* Use this if groundsMemo is JSX */}
      <ul>{groundsMemo}</ul>

      {/* Use this if groundsMemo is an Array (data) */}
      <ul>{groundsMemo.map(item => <li key={some_key}>
        {item.property}
      </li>)}</ul>
    </div>
  )
}

尝试使用useMemouseCallBack你想优化你的反应应用程序。 React 官方文档清楚地描述了如何使用它: useMemo useCallBack

您永远不应该在渲染的返回 scope 中调用 function。 组件在没有适当处理的情况下重新渲染是正常的。

考虑其他2个答案

您可以使用 useEffect、useCallback 和 React.memo 的全部功能来防止任何东西重新渲染。

import React from 'react';
import grounds  from './../../UballersGroundsData.json';

function Groundlist() {
  // initiate state
  const [names, setNames] = React.useState([]);

  // This will prevent the Function from recalculate - useCallback
  const getNames = React.useCallback(function (jsonObj) {
    for(let item in jsonObj){
      console.log("item = " + item);
      for(let property in jsonObj[item] ){
        console.log(jsonObj[item]);
        // if (property === "groundName"){
        //     console.log(jsonObj[item][property]);
        // }
      }
    }
  }, []);
  

  // Will make function run only once and nevermore - useEffect
  React.useEffect(() => {
    setNames(getNames());
  }, [])

  return(
    <div>
        <h1>Hello world!</h1>
        <ul>
            {names.map(a => <li>{a}</li>)}
        </ul>

    </div>
  )
}

// Will prevent React from try to re-render without changing in props, so as your component has no props, will never re-render without yourself unmounting first
export default React.memo(Groundlist);

在另一种情况下,您可以使用函数的最后一个参数精确控制组件何时重新计算您的名称

useCallback(() => {}, []) //<---

例如

useCallback(() => {}, [updateState]);

当 updateState 改变 function 将被重新创建。

暂无
暂无

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

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