自定义挂钩导致性能不佳,尽管使用 useCallback 进行优化不会反映新状态
Custom hook cause poor performance, although optimizing with useCallback will not reflect the new state
我正在做一些 React Hooks 实验,遇到了一个漂亮的轰炸问题。
我正在尝试创建自定义表单状态挂钩。
我创建了一个非常非常简化的版本 我的工作只是为了证明这里的问题:https://repl.it/@kadoshms/useCallbackCapture
代码本身在这里(为了简单起见,我将所有代码放在同一个主文件中):
import React, { Component, useState, useCallback } from 'react';
import logo from './logo.svg';
import './App.css';
const myHook = (e) => {
const [values, setValues] = useState({
checked: []
});
const setFormValues = useCallback((e) => {
// some logic
if (e.currentTarget.checked) {
setValues({
checked: [...values.checked, e.currentTarget.value]
});
} else {
setValues({
checked: values.checked.filter(v => v !== e.currentTarget.value)
});
}
}, []);
return [values, setFormValues];
}
const checkboxes = Array.from({length: 222}, (v, k) => k+1);
const Checkbox = (props) => (
<input type="checkbox"
name={props.name}
value={props.value}
checked={props.checked} onChange={props.onChange} />
);
// Checkbox.whyDidYouRender = true;
const Form = () => {
//
const [formData, setFormData] = myHook();
return (
<form>
{checkboxes.map((c) => <Checkbox name="foo" checked={formData['checked'].includes(c.toString())}
key={`c-${c}`}
onChange={setFormData} value={c} />)}
</form>
);
//
};
class App extends Component {
render() {
return (
<div className="App">
<Form />
</div>
);
}
}
export default App;
这个问题在我提供的示例中几乎是不言自明的。
useCallback 挂钩可能会捕获导致 checked
数组不更新的最后状态。
添加 formData
作为依赖项,或者另一方面删除记忆将修复它。
不过,这可能会导致性能问题,因为 onChange 处理程序在每次渲染时都会关闭。
我的目标是使用 hooks 但保持良好的性能,因此每个复选框只有在 checked 值更改时才应该更新。
编辑: 我可以使用自定义 React.memo 回调解决问题,类似于 shouldComponentUpdate,但我认为它不太优雅。
这可能吗?
提前致谢。
进一步阅读后,我在 React 官方文档中遇到了以下常见问题解答部分:https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-because-of-creating-functions-in-render
TL:DR: 我没有使用 useState
,而是使用 useReducer
钩子创建了一个 reducer,就像文档中指定的那样。
如果有人感兴趣,我很乐意分享我针对上述特定问题的解决方案。
我正在做一些 React Hooks 实验,遇到了一个漂亮的轰炸问题。
我正在尝试创建自定义表单状态挂钩。 我创建了一个非常非常简化的版本 我的工作只是为了证明这里的问题:https://repl.it/@kadoshms/useCallbackCapture
代码本身在这里(为了简单起见,我将所有代码放在同一个主文件中):
import React, { Component, useState, useCallback } from 'react';
import logo from './logo.svg';
import './App.css';
const myHook = (e) => {
const [values, setValues] = useState({
checked: []
});
const setFormValues = useCallback((e) => {
// some logic
if (e.currentTarget.checked) {
setValues({
checked: [...values.checked, e.currentTarget.value]
});
} else {
setValues({
checked: values.checked.filter(v => v !== e.currentTarget.value)
});
}
}, []);
return [values, setFormValues];
}
const checkboxes = Array.from({length: 222}, (v, k) => k+1);
const Checkbox = (props) => (
<input type="checkbox"
name={props.name}
value={props.value}
checked={props.checked} onChange={props.onChange} />
);
// Checkbox.whyDidYouRender = true;
const Form = () => {
//
const [formData, setFormData] = myHook();
return (
<form>
{checkboxes.map((c) => <Checkbox name="foo" checked={formData['checked'].includes(c.toString())}
key={`c-${c}`}
onChange={setFormData} value={c} />)}
</form>
);
//
};
class App extends Component {
render() {
return (
<div className="App">
<Form />
</div>
);
}
}
export default App;
这个问题在我提供的示例中几乎是不言自明的。
useCallback 挂钩可能会捕获导致 checked
数组不更新的最后状态。
添加 formData
作为依赖项,或者另一方面删除记忆将修复它。
不过,这可能会导致性能问题,因为 onChange 处理程序在每次渲染时都会关闭。
我的目标是使用 hooks 但保持良好的性能,因此每个复选框只有在 checked 值更改时才应该更新。
编辑: 我可以使用自定义 React.memo 回调解决问题,类似于 shouldComponentUpdate,但我认为它不太优雅。
这可能吗?
提前致谢。
进一步阅读后,我在 React 官方文档中遇到了以下常见问题解答部分:https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-because-of-creating-functions-in-render
TL:DR: 我没有使用 useState
,而是使用 useReducer
钩子创建了一个 reducer,就像文档中指定的那样。
如果有人感兴趣,我很乐意分享我针对上述特定问题的解决方案。