Reactjs 跳过效果不适用于动态URL';s
我有一个React.SFC/React stateless/functional组件,不幸的是,由于父组件中的redux传入了一些多余的数据,该组件呈现的频率有点太高。目前对此我无能为力,所以我只接受额外的重新渲染器,并使用useEffect确保只在某个属性发生更改时才获取数据。在本例中,它被称为“URL”,是URL的数组(TypeScript URL类型) 下面是一些示例代码,说明了该问题:Reactjs 跳过效果不适用于动态URL';s,reactjs,react-hooks,Reactjs,React Hooks,我有一个React.SFC/React stateless/functional组件,不幸的是,由于父组件中的redux传入了一些多余的数据,该组件呈现的频率有点太高。目前对此我无能为力,所以我只接受额外的重新渲染器,并使用useEffect确保只在某个属性发生更改时才获取数据。在本例中,它被称为“URL”,是URL的数组(TypeScript URL类型) 下面是一些示例代码,说明了该问题: import React from "react"; import { useState, useEf
import React from "react";
import { useState, useEffect, useMemo } from "react";
import { render } from "react-dom";
import "./styles.css";
const useCustomHook = urls => {
const [onlyChangeWhenUrlsChange, setOnlyChangeWhenUrlsChange] = useState(
null
);
useEffect(
() => {
setOnlyChangeWhenUrlsChange(Math.random());
},
[urls]
);
return onlyChangeWhenUrlsChange;
};
const dynamicUrls = (pageRouteParamId, someDynamicUrlParam) => {
return [
{
pageRouteParamId: 1337,
urls: [new URL(`https://someurl.com/api?id=${someDynamicUrlParam}`)]
}
];
};
const SomePage: React.SFC<any> = ({
simulateFrequentUpdatingData,
pageRouteParamId
}) => {
const someOtherId = 1;
// As suggested in SO answer, using useMemo seems to work, but will that not create a memory leak?
// Is there any good alternative?
// const urls = useMemo(() => dynamicUrls(pageRouteParamId, someOtherId).find(url => url.pageRouteParamId === pageRouteParamId).urls, [pageRouteParamId, someOtherId]);
const urls = dynamicUrls(pageRouteParamId, 1).find(
url => url.pageRouteParamId === 1337
).urls;
return (
<div>
<p>parent</p>
<p>{simulateFrequentUpdatingData}</p>
<p>
Page route param id (in real app this would come from react-router route
param): {pageRouteParamId}
</p>
{urls && urls.length && <MyStateLessFunctionalComponent {...{ urls }} />}
<p>
Page route param id (in real app this would come from react-router route
param): {pageRouteParamId}
</p>
{urls && urls.length && (
<MyStateLessFunctionalComponentWithHook {...{ urls }} />
)}
</div>
);
};
const MyStateLessFunctionalComponent: React.SFC<any> = ({ urls }) => {
const [onlyChangeWhenUrlsChange, setOnlyChangeWhenUrlsChange] = useState(
null
);
useEffect(
() => {
setOnlyChangeWhenUrlsChange(Math.random());
},
[urls]
);
return (
<div>
<p>MyStateLessFunctionalComponent</p>
<p>{JSON.stringify(urls)}</p>
<p>This should only change when urls change {onlyChangeWhenUrlsChange}</p>
</div>
);
};
const MyStateLessFunctionalComponentWithHook: React.SFC<any> = ({ urls }) => {
const onlyChangeWhenUrlsChange = useCustomHook(urls);
return (
<div>
<p>MyStateLessFunctionalComponentWithHook</p>
<p>{JSON.stringify(urls)}</p>
<p>This should only change when urls change {onlyChangeWhenUrlsChange}</p>
</div>
);
};
function App() {
const [
simulateFrequentUpdatingData,
setSimulateFrequentUpdatingData
] = useState(null);
const [pageRouteParamId, setPageRouteParamId] = useState(1337);
useEffect(() => {
setInterval(() => setSimulateFrequentUpdatingData(Math.random()), 1000);
}, []);
return (
<div className="App">
<SomePage {...{ simulateFrequentUpdatingData, pageRouteParamId }} />
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
从“React”导入React;
从“react”导入{useState、useEffect、useMemo};
从“react dom”导入{render};
导入“/styles.css”;
const useCustomHook=URL=>{
const[onlychangewerlschange,setonlychangewerlschange]=useState(
无效的
);
使用效果(
() => {
setonlychangewerlschange(Math.random());
},
[网址]
);
仅返回更改WherNursChange;
};
常量dynamiccurls=(pageRouteParamId,SomedynamiccurlParam)=>{
返回[
{
pageRouteParamId:1337,
URL:[新URL(`https://someurl.com/api?id=${somedynamicCurlParam}`)]
}
];
};
const SomePage:React.SFC
正如下面的答案中所建议的,useMemo似乎解决了这个问题(参见第36行)我的猜测是,URL
是在树的更高的渲染中声明的,因此每次都会获得一个新的标识。您可以在声明位置usemo
将deps数组中的url
字符串化,也可以使用useRef
防止重新运行
编辑:比我聪明的人正在讨论这个问题: 如果url
是字符串数组,则可以将其作为第二个参数传递给useffect
useEffect(() => {
loadData();
}, urls);
这样,它将检查字符串值,而不是数组引用 有趣。无论有没有自定义挂钩,它都应该能正常工作。你认为你可以在例如中创建一个钩子吗?是的,无论它是自定义钩子,它的行为都应该是相同的。你的url
道具是什么样子的?即使道具是静态的,它也会重复播放多次?当我回到电脑时,我会制作一个运行片段。(注意第36行)-不幸的是,我得出了错误的结论,在直接使用useEffect和通过另一个钩子使用useEffect时,这确实也是一个问题。我想我需要编辑标题和问题:/URL是从父组件中的函数生成的(也是无状态的,所以在render中是)。但是如果我直接在子组件MyStateLessFunctionalComponent中使用useEffect,它就会起作用。为什么会有不同?我有点不好意思承认,但你的猜测是正确的。不幸的是,我在写这篇文章时得出了错误的结论。我不确定我是否应该批准你的答案并编辑帖子以适应useMemo的答案,或者干脆取消这个问题。关于useMemo,我认为开始使用它是一个很滑的斜坡,但是在我的例子中,URL是基于特定页面/路径的唯一id的动态的,除了使用memo和潜在的内存泄漏之外,还有其他方法吗?这里的实例:(注意第36行)我认为使用useMemo
不会有内存泄漏的风险,我很确定它只会在内存中保存最后一个已记忆的值。任何旧值都应该被垃圾回收。然而,这让我很担心:“编写代码,使其在没有useMemo的情况下仍能工作,然后添加代码以优化性能。”然而Dan Abramov在我在回答中链接的问题中使用了它。谢谢。读同一行,也有同样的担忧。:-)它是一个URL数组(Typescript URL类型)。