我试图了解用React的useCallback钩子代替钩子的用例是什么useEffect。
它们似乎都充当其输入的状态更改的侦听器(示例取自React Docs):
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
Run Code Online (Sandbox Code Playgroud)
但是,该useEffect钩子还具有清理资源的额外好处,而您以前可能会使用componentWillUnmount。
那么,有什么好的用例useCallback呢?而且,我在这里想念什么?
我正在建造一个 <BasicForm>组件,用于在我的应用程序中构建表单。它应该处理提交、验证并且还应该跟踪输入状态(如触摸、脏等)。
因此,它需要一些函数来完成所有这些,我一直想知道放置这些声明的最佳位置是什么(关于代码组织和性能优化,考虑 React 和 JavaScript 最佳实践)。
我正在使用 React 16.8 钩子并与 Webpack 捆绑。
到目前为止,这是我所拥有的:
基本表单.js
/* I moved those validating functions to a different file
because I thought they are helpers and not directly related
to my BasicForm functionality */
import { validateText, validatePassword, validateEmail } from './Parts/ValidationHelpers';
function BasicForm(props) {
const [inputs, setInputs] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
// These are functions to handle these events
function onChange(event) {...}
function onBlur(event) {...}
function onFocus(event) {...}
// …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用新的 Hooks 从类组件转向功能组件。然而,感觉与useCallback类组件中的类函数不同,我会得到不必要的子元素渲染。
下面我有两个相对简单的片段。第一个是我编写为类的示例,第二个是我将示例重写为功能组件。目标是让功能组件获得与类组件相同的行为。
类组件测试用例
class Block extends React.PureComponent {
render() {
console.log("Rendering block: ", this.props.color);
return (
<div onClick={this.props.onBlockClick}
style = {
{
width: '200px',
height: '100px',
marginTop: '12px',
backgroundColor: this.props.color,
textAlign: 'center'
}
}>
{this.props.text}
</div>
);
}
};
class Example extends React.Component {
state = {
count: 0
}
onClick = () => {
console.log("I've been clicked when count was: ", this.state.count);
}
updateCount = () => {
this.setState({ count: this.state.count + 1});
};
render() …Run Code Online (Sandbox Code Playgroud)前言/说明
我正在尝试将React的新挂钩函数用于我正在构建的电子商务网站,但是在解决购物车组件中的错误时遇到了问题。
我认为以我想通过使用多个Context组件保持全局状态模块化的事实作为开始讨论的重点。对于我提供的商品类型,我有一个单独的上下文组件,对于一个人的购物车中的商品,我有一个单独的上下文组件。
问题
我遇到的问题是,当我调度将组件添加到购物车的操作时,减速器将运行两次,就像我两次将商品添加到购物车一样。但是仅当它最初被渲染时,或者由于诸如显示之类的奇怪原因而被设置为hidden,然后又返回到block或由于z-index和可能的其他类似更改而改变。
我知道这有点冗长,但这是一个很挑剔的问题,因此我创建了两个演示该问题的代码笔:
您将看到我包含一个用于切换display组件的按钮。这将有助于展示CSS与问题的相关性。
最后,请用代码笔监视控制台,这将显示所有按钮的单击以及每个reducer的哪一部分已运行。在完整示例中,问题最明显,但在最小示例中,控制台语句显示了该问题。
问题区域
我已查明该问题与以下事实有关:我正在使用useContext挂钩的状态来获取项目列表。调用了一个函数来为我的useReducer钩子生成化简器,但是仅当使用了另一个钩子时才出现,我可以使用像钩子一样不会重新评估的函数,并且没有问题,但是我还需要我以前的上下文中的信息,因此解决方法无法真正解决我的问题。
相关连结
我已确定问题不是HTML问题,因此我将不包含我尝试过的HTML修复程序的链接。这个问题虽然是由CSS触发的,但并非植根于CSS,因此我也不会包含CSS链接。
在反应课上,我会写这样的东西
class Myclass extends React.Component {
handleUpdate = info => {
//do the update
}
render() {
return (
<SomeMarkup>
<SomeComponent onUpdate={this.handleUpdate} />
</SomeMarkup>
)
}
}
Run Code Online (Sandbox Code Playgroud)
如果使用函数,我可以只写以下内容
function MyFunction() {
function handleUpdate(info) {
// do the update
}
return (
<SomeMarkup>
<SomeComponent onUpdate={handleUpdate} />
</SomeMarkup>
)
}
Run Code Online (Sandbox Code Playgroud)
...但是我会在每次渲染时重新声明一个函数。有没有什么技巧可以记住渲染之间的处理函数?或者我应该将处理程序移出渲染范围?(将它移出渲染范围需要我明确传递更多参数,因为我不会直接访问函数范围。)
当向一个PureComponent或功能组件发送 props 时,你可以通过使用不会在每次渲染时改变的 props 来优化性能,这将阻止组件重新渲染。
使用类组件时,这很简单:
class Component extends React.Component {
render() {
return <List createRows={this.createRows}/>;
}
createRows = () => this.props.data.map(dataToRow);
}
Run Code Online (Sandbox Code Playgroud)
鉴于List是一个PureCompoment或功能组件,createRows道具永远不会导致重新渲染List.
但是如果Component是一个功能组件,这将不再可能:
function Component(props) {
return <List createRows={createRows}/>;
function createRows() {
return props.data.map(dataToRow);
}
}
Run Code Online (Sandbox Code Playgroud)
由于createRows每次Component渲染时都会创建,因此道具会发生变化,导致List每次重新渲染时都会Component重新渲染。这会导致性能的巨大损失。还要注意createRows不能放置在功能组件之外,因为它依赖于 的data道具List。
现在,随着 Hooks 的介绍,可以将 保持createRows在一个useState钩子中:
function Component(props) {
const [ createRows …Run Code Online (Sandbox Code Playgroud)