我的代码有问题。我的函数“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>
)
}
谢谢!
答案 0 :(得分:1)
您应该将函数放在 useEffect hook 中,然后使用 useState 将其设置为 state hook。然后,为您的列表绘制列表项(假设您正在从您的函数返回一个数组)。如果您希望它只在第一次渲染时运行 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>
)
}
答案 1 :(得分:1)
您可以使用 useMemo 反应钩子来记住返回的值,即跳过由于其他状态、道具或上下文变量的变化而导致的不必要/繁重的计算。
示例:
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>
)
}
答案 2 :(得分:0)
尝试使用 useMemo
和 useCallBack
来优化您的 React 应用。
React 官方文档清楚地描述了如何使用它:useMemo
useCallBack
答案 3 :(得分:0)
您永远不应该在渲染的返回范围内调用函数。 组件在没有适当处理的情况下重新渲染是正常的。
考虑其他 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 更改时,将重新创建该函数。