reactjs - React 中的渲染和最佳实践
问题描述
我是 React 的初学者,我有一个关于渲染的问题,其中包括我使用 useEfect 来渲染变量中的变化,该变量在 useState 中装饰
以下是声明:
const CardRepo: React.FC<DadosCardRepo> = ({ Nome }) => {
const [nomeRepo, setNomeRepo] = useState(Nome);
const [data, setData] = useState({});
const [languages, setLanguages] = useState<Languages[]>([]);
这是一个组件,它接收一个带有Name的对象,并在nameRepo中设置这个值Name
以下是两种方法:
useEffect(() => {
getRepo(nomeRepo)
.then(data => {
setData(data);
});
}, [nomeRepo]);
useEffect(() => {
getLanguages(data['languages_url'])
.then(data => {
let total = 0;
const languagesRef: Languages[] = [];
Object.keys(data).map((key) => {
total += data[key];
languagesRef.push({ Nome: key, Porct: data[key] });
});
languagesRef.map((language, i, array) => {
setLanguages((oldValues) => [...oldValues, { Nome: language.Nome.toLowerCase(), Porct: +((language.Porct * 100) / total).toFixed(2) }]);
});
});
}, [data]);
我在更改 nomeRepo 时运行的第一个 useEfect,在此方法中,我向 getRepo 服务发出请求
第二个,当我更改日期时,在此方法中,我向 getLanguages 服务发出请求,并对响应进行处理以用它制作一个列表,在那里我分配语言。
这是清单:
{
languages.map((el, i) => {
return (
<div className="progress-bar" id={el.Nome} key={i} style={{ width: el.Porct + '%' }}></div>
);
})
}
我的问题与渲染有关,我知道我只能列出一些东西,如果我在变量“语言”中使用 useEfect,我将在其中分配值并使用变量中的更改再次渲染,否则我不能。
但是当我对代码进行任何更改时,它只呈现更改的位置,但它分配的值与分配的相同,例如:[1,2,3] => [1,2,3,1 ,2,3]。我试图把 setLanguages([]),但它具有相同的行为,我想知道如何解决这个问题,以及以这种方式进行调用和列出是否是一个好习惯。
解决方案
首先,有一种不好的做法是从道具创建派生状态。nomeRepo
来自 props Nome
,你应该尽量避免这种派生状态。您最好删除nomeRepo
状态并仅使用Nome
.
您的第一次使用效果变为:
useEffect(() => {
getRepo(Nome)
.then(data => {
setData(data);
});
}, [Nome]);
你第二个useEffect
在setState
地图内触发了。这将多次触发您的 setState,创建多个重新渲染。最好先准备好你的语言数组,然后调用setState
一次。
此外,如果您不使用返回的数组,并且只在每个元素上运行一些脚本,则应该使用forEach
而不是。map
需要注意的一件事是,您正在向旧语言添加新语言。我假设语言应该是相关data['languages_url']
的值,这样你就不会将旧语言包含到 setLanguages 中。
您可以考虑的一件事是保留您的总值而不是百分比。您可以使用useMemototal
存储到变量中,这取决于. 并将您的百分比函数声明到文件夹中并根据需要将其导入。languages
utils
重构第二个 useEffect:
// calculate total value that gets memoized
const totalLangCount = useMemo(() => languages.reduce((total, val) => total + val.count , 0), [languages])
useEffect(() => {
getLanguages(data['languages_url'])
.then(data => {
const languagesRef: Languages[] = [];
Object.keys(data).forEach((key) => {
// prepeare your languages properties
const nome = key.toLowerCase();
const count = data[key];
languagesRef.push({ nome, count });
});
// avoid multiple setLanguages calls
setLanguages(languagesRef)
});
}, [data]);
呈现的语言:
{
languages.map((el, i) => {
return (
// here we are using array's index as key, but it's best to use some unique key overall instead
<div className="progress-bar" id={el.nome} key={i} style={{ width: percentage(el.count, total) }}></div>
);
})
}
百分比函数可重用:
// utils percentage exported
export const percentage = (count, total) => ((count * 100) / total).toFixed(2) + '%'
推荐阅读
- reactjs - 反应有事件的大日历样式日期
- autosys - 如何在 jil 中加载 Autosys 配置文件
- dart - Flutter / flutter_webview_plugin => 向下/向上滚动时隐藏/显示 AppBar + BottomNavigationBar
- java - EditText 可以显示或容纳多少文本?
- javascript - 电子修改单个菜单项?
- c# - Lambda 表达式:从较大的字符串中挑选出一个子字符串
- javascript - 如何使用 D3.js 在 HTML 元素中创建换行符
- java - 是否有从 oracle 结果集中检索二进制 XML 的功能
- javascript - Jquery Clone 克隆后提交表单
- angular - this.standardizeDate[language] 不是函数