- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遇到了一个性能优化问题,我认为可以通过某种方式解决该问题,但我不确定如何解决。
假设我有一个想要可编辑的对象集合。父组件包含所有对象,并使用编辑器组件呈现一个列表,该组件显示值并允许修改对象。
一个简化的例子是这样的:
import React, { useState } from 'react'
const Input = props => {
const { value, onChange } = props
handleChange = e => {
onChange && onChange(e.target.value)
}
return (
<input value={value} onChange={handleChange} />
)
}
const ObjectEditor = props => {
const { object, onChange } = props
return (
<li>
<Input value={object.name} onChange={onChange('name')} />
</li>
)
}
const Objects = props => {
const { initialObjects } = props
const [objects, setObjects] = useState(initialObjects)
const handleObjectChange = id => key => value => {
const newObjects = objects.map(obj => {
if (obj.id === id) {
return {
...obj,
[key]: value
}
}
return obj
})
setObjects(newObjects)
}
return (
<ul>
{
objects.map(obj => (
<ObjectEditor key={obj.id} object={obj} onChange={handleObjectChange(obj.id)} />
))
}
</ul>
)
}
export default Objects
所以我可以使用React.memo
,这样当我编辑一个对象的名称时,其他对象就不会重新渲染。但是,由于 onChange
处理程序每次都会在 ObjectEditor
的父组件中重新创建,因此所有对象始终都会呈现。
我无法通过在处理程序上使用 useCallback
来解决这个问题,因为我必须将我的 objects
作为依赖项传递给它,而每次对象的名称都会重新创建它变化。
在我看来,由于处理程序发生了变化,所有未更改的对象都没有必要重新渲染。应该有一种方法可以改进这一点。
有什么想法吗?
我在 React Sortly 存储库中看到,他们将 debounce
与每个对象编辑器结合使用来更改其自身状态。这仅允许编辑的组件在有人键入时进行更改和重新渲染,并且如果在给定延迟内没有其他更改事件出现,则仅更新父组件一次。
handleChangeName = (e) => {
this.setState({ name: e.target.value }, () => this.change());
}
change = debounce(() => {
const { index, onChange } = this.props;
const { name } = this.state;
onChange(index, { name });
}, 300);
这是我现在能看到的最好的解决方案,但由于他们使用 setState
回调函数,我无法找到一种方法来使其与钩子(Hook)一起工作。
最佳答案
您必须使用setState
的函数形式:
setState((prevState) => {
// ACCESS prevState
return someNewState;
});
您将能够在更新时访问当前状态值 (prevState)。
这样您就可以使用 useCallback
Hook ,而无需将状态对象添加到依赖项数组中。 setState
函数不需要位于依赖项数组中,因为它不会在渲染过程中发生更改。
因此,您将能够在子级上使用 React.memo
,并且只有接收到不同 Prop (浅比较)的子级才会重新渲染。
下面片段中的示例
const InputField = React.memo((props) => {
console.log('Rendering InputField '+ props.index + '...');
return(
<div>
<input
type='text'
value={props.value}
onChange={()=>
props.handleChange(event.target.value,props.index)
}
/>
</div>
);
});
function App() {
console.log('Rendering App...');
const [inputValues,setInputValues] = React.useState(
['0','1','2']
);
const handleChange = React.useCallback((newValue,index)=>{
setInputValues((prevState)=>{
const aux = Array.from(prevState);
aux[index] = newValue;
return aux;
});
},[]);
const inputItems = inputValues.map((item,index) =>
<InputField
value={item}
index={index}
handleChange={handleChange}
/>
);
return(
<div>
{inputItems}
</div>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
关于reactjs - 当回调在父级中更改状态时,如何使用 React.memo 和 useCallback 优化 React 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57822144/
我正在尝试通过容器将 Redux mapStateToProps() 和 mapActionCreators() 连接到登录屏幕,并且我正在使用 React 导航。 构建我的应用程序后,出现以下错误消
你能告诉我为什么我的标题每次渲染都已经使用了 React.memo 吗? 当我从 导航时,我有两个部分 my app and user我的应用程序 到 user header 重新呈现为什么? 这是我
我正在尝试在 React 应用程序中插入 google maps map 。我宁愿不使用非官方图书馆(我发现那些缺乏文档的图书馆),而且我已经成功地插入了 map 。 我的问题是每次父组件的状态改变时
我有一个父组件,它根据通过 props 接收到的数组来渲染子组件的集合。 import React from 'react'; import PropTypes from 'prop-types';
我只是使用 redux 和react-redux connect 函数以及状态和调度来连接应用程序。编译没有问题,但结果没有显示。如下所示。 我尝试查找,发现必须更换react版本。 $ sudo n
我习惯了export default React.memo(SomeComponent);所以 React 可以内存我的组件。 但是在我使用命名导出的文件中。如何使用 React.memo() ? e
我正在创建一个函数备忘录,返回一个函数,该函数在调用时将检查它是否已经计算出给定参数的结果,并在可能的情况下返回该值。 现在我的 key 仅包含作为我的 key 传入的第一个参数,以检查该函数是否已经
考虑以下简单组件: import React, { Fragment, memo } from 'react'; function Parent(props) { return (
我的父组件处理对服务器的请求并为其子组件提供来自响应的数据。在这种情况下,一个子组件(FilterSidebar:包含过滤器组件)应该只呈现一次,因为过滤器将从初始请求的数据创建。 这就是为什么我要使
是否可以将 React.memo 应用于带有 for 循环的组件数组? 假设我有以下三个组件: const Item1 = (props) => { const { index } = pro
我到处搜索有关此信息,似乎Access中的DAO参数限制为255个字符。 真的吗?仍然?即使在Office 2010中?看来很荒谬。我宁愿不切换到ADO,但在这一点上看来我必须这样做。 在仍然使用DA
每次我的选项卡组件父组件重新呈现时,我的子组件也会重新呈现。 我的标签组件父级如下 import { useState } from "react"; import "./styles.scss";
我正在重构我们的一些组件,所以我试图将 memoization 作为一些组件合并 5 月 使用相同的值重新渲染(例如,热链接图像 URL,除非它们相同)。 我有一个简单的组件: const CardH
我不想在某些路径上重新渲染我的组件,尝试使用 React.memo 并使用 withRouter HOC 检查当前路径。 React.memo 中的比较函数没有被调用。 function compar
我使用 React 前端制作了一个国际象棋游戏。最初,任何 Action 似乎都是瞬间实现的,但是在添加了额外的功能之后,比如改变标题的背景以反射(reflect)轮到谁了(白色或黑色背景取决于它的白
我正在尝试制作一个聊天应用程序,它将以如下形式将消息发布到备忘录中: USERNAME-> Message 但它像这样发布到我的备忘录中: USERNAME 这是我的代码: const cnMax
在 documentation for React.memo ,它说: This method only exists as a performance optimization. Do not re
有人知道当使用react-redux中的connect函数时如何用React.memo包装React组件吗? 例如,您将如何修改以下内容? let Button = (props: Props) =>
以下代码来自 Pathikrit's Dynamic Programming存储库。 我对它的美丽和独特性感到困惑。 def subsetSum(s: List[Int], t: Int) = {
我正在使用 Apollo GraphQL 中的 useMutation Hook ,并且我想使用 onCompleted 属性执行特定任务。基本上,我想在 useMutation 成功完成时执行 se
我是一名优秀的程序员,十分优秀!