我正在努力解决我的 React 应用程序的性能问题。例如,我有一个卡片列表,您可以添加像 Facebook 一样的卡片。一旦其中一个子项更新,所有列表都会重新渲染,所以在这里我尝试使用 useMemo 或 React.memo。我以为我可以使用 React.memo 作为卡片组件,但没有成功。不确定我是否遗漏了一些重要的部分..
父.js
const Parent = () => {
const postLike= usePostLike()
const listData = useRecoilValue(getCardList)
// listData looks like this ->
//[{ id:1, name: "Rose", avararImg: "url", image: "url", bodyText: "text", liked: false, likedNum: 1, ...etc },
// { id:2, name: "Helena", avararImg: "url", image: "url", bodyText: "text", liked: false, likedNum: 1, ...etc },
// { id: 3, name: "Gutsy", avararImg: "url", image: "url", bodyText: "text", liked: false, likedNum: 1, ...etc …Run Code Online (Sandbox Code Playgroud) 据我了解,两者之间的区别在于,如果返回函数、对象或数组,则使用 useCallback,而返回原语时则使用 useMemo。但我正在查找去抖(这是文章: https: //dmitripavlutin.com/react-throttle-debounce/,它说 useMemo 将是一个更好的解决方案。使用 useCallback
import { useState, useCallback } from 'react';
import debounce from 'lodash.debounce';
export function FilterList({ names }) {
const [query, setQuery] = useState("");
let filteredNames = names;
if (query !== "") {
filteredNames = names.filter((name) => {
return name.toLowerCase().includes(query.toLowerCase());
});
}
const changeHandler = event => {
setQuery(event.target.value);
};
const debouncedChangeHandler = useCallback(
debounce(changeHandler, 300)
, []);
return (
<div>
<input
onChange={debouncedChangeHandler}
type="text"
placeholder="Type a query..."
/>
{filteredNames.map(name => <div key={name}>{name}</div>)}
</div> …Run Code Online (Sandbox Code Playgroud) 这是我的 React hooks 代码:
function calc_c({a,b}){
//some long calculation that is based on a,b
}
function MyComponent(params){
var a=calc_a(params)
var a=calc_b(params)
var c=React.useMemo(()=>calc_c({a,b},[a,b])
}
Run Code Online (Sandbox Code Playgroud)
我的问题:如何找出哪些参数发生了[a,b]变化并导致了调用calc_c
编辑:我最终使用了 skyboyer 优秀答案的通用版本:
export function useChanged(name,value){
function print_it(){
console.log('changed',name)
}
React.useMemo(print_it,[value])
}
Run Code Online (Sandbox Code Playgroud) 寻找一些 React 渲染/useMemo 指南。
我有一个包含 2,000 多个项目的列表,每个项目都是一个 React 组件。有一个“当前选定”项目的突出显示,该项目独立于列表呈现。这允许我只渲染列表一次。
useMemo(_ => {
<Item .../>
<Item .../>
...
<Item .../>
}, [contents])
Run Code Online (Sandbox Code Playgroud)
现在我添加了“展开”其中的列表项的功能,这只会添加新的 DOM 元素,而不会修改处于非展开状态的列表项。
您可以将每个部分想象Item为两部分:
function Item(props) {
return
<div>
<SubItem />
{
if (props.open) {
<OtherItem />
} else {
null
}
}
</div>
}
Run Code Online (Sandbox Code Playgroud)
useMemo(_ => {
<Item open={1 == current} .../>
<Item open={2 == current} .../>
...
<Item open={n == current} .../>
}, [contents, current])
Run Code Online (Sandbox Code Playgroud)
问题:有没有一种方法可以支持这一点,而不必在每次展开/折叠新项目时重新渲染整个列表?
不幸的是,扩展的 DOM 元素是“流动的”,因此扩展会将列表项推到它后面(不仅仅是悬停/覆盖)。
我正在开发一个相对较大的 React 代码库,并且我看到以前的开发人员使用memo并usecallback自由地认为通过使用这些代码可以提高性能。显然不是,这是一个例子
export default function QuestionHelper({ text }: { text: string }) {
const [show, setShow] = useState<boolean>(false);
const open = useCallback(() => setShow(true), [setShow]);
const close = useCallback(() => setShow(false), [setShow]);
return (
<span style={{ marginLeft: 4 }}>
<Tooltip show={show} text={text}>
<QuestionWrapper
onClick={open}
onMouseEnter={open}
onMouseLeave={close}
>
<Question size={16} />
</QuestionWrapper>
</Tooltip>
</span>
);
}
Run Code Online (Sandbox Code Playgroud)
该应用程序现在可以运行。但我拒绝修复它,因为该应用程序按预期工作。我怎样才能证明我们应该删除代码中所有不必要的memo和?usecallback
是否有客观的方法来说明删除这些内容的好处?
无论React.memo和useMemo钩通过减少重新计算和重新描绘允许性能优化。然而,它们确实有效,因为 React.memo 用于包装函数组件,并且useMemo钩子几乎可以用于任何函数,甚至是纯计算。更重要的useMemo是,通常从父组件React.memo调用子组件,而通常在子组件本身的声明上调用。
虽然两者都有不同的优点,但一个优点React.memo是不必从每个父子关系中调用它。然而,随着钩子的发布,很明显 React 开发希望转向使用钩子来处理状态、副作用事件和其他效果的功能组件。虽然我认为 React 开发团队不会有勇气或无视他们的用户群React.memo在未来 2 年内随时删除,但我想知道他们是否希望最终用户出于风格原因停止使用 React.memo。就像他们有种被动积极地从类组件转移到带有钩子的功能组件。
当使用带有钩子的功能组件时,react 框架是否正在远离React.memo? 如果将来想跟上 React 最佳实践,习惯使用钩子版本会更好吗?
从 useMemo 返回或包装在 React.memo() 中的子组件是否也被记忆?(抱歉,这可能是一个愚蠢的问题)
例如:
React.memo(<Parent><Child/></Parent>);
Run Code Online (Sandbox Code Playgroud)
这里Parent被记忆了,Child是否也被记忆了?
在外面柜台在很多的YouTube视频教程看到的例子,什么是实用/现实世界中使用案例useMemo和useCallback?
另外,我只看到了钩子的输入焦点示例useRef。
请分享您为这些钩子找到的其他用例。
我正在尝试渲染必须通过的数据useMemo。我从 api 调用获取数据,因此我调用useEffect. 初始渲染工作返回一个空数组,但是一旦我调用 api,数据就不会更新。
import React from 'react'
import {fetchAccounts} from '../utils/api'
export default function Accounts() {
const [accounts, setAccounts] = React.useState([])
React.useEffect(() => {
setLoading(true)
fetchAccounts().then((data) => {
setAccounts(data)
})
}, [])
const data = React.useMemo(() => accounts, [])
return <p>{JSON.stringify(data)}</p>}
Run Code Online (Sandbox Code Playgroud)
那么这可以在单个组件中工作吗?或者必须创建自定义挂钩?
reactjs ×9
react-hooks ×7
usecallback ×3
javascript ×2
memo ×1
memoization ×1
performance ×1
react-memo ×1
recoiljs ×1
render ×1
use-effect ×1
use-ref ×1