在基于类的 React 组件中,我执行如下操作:
class SomeComponent extends React.Component{
onChange(ev){
this.setState({text: ev.currentValue.text});
}
transformText(){
return this.state.text.toUpperCase();
}
render(){
return (
<input type="text" onChange={this.onChange} value={this.transformText()} />
);
}
}
为了简化我的观点,这是一个人为的例子。我本质上想要做的是保持对 onChange 函数的持续引用。在上面的例子中,当 React 重新渲染我的组件时,如果输入值没有改变,它不会重新渲染输入。
这里要注意的重要事项:
- this.onChange 是对同一函数的常量引用。
- this.onChange 需要能够访问状态 setter (在本例中为 this.setState)
现在如果我要使用钩子(Hook)重写这个组件:
function onChange(setText, ev) {
setText(ev.currentValue.text);
};
function transformText(text) {
return text.toUpperCase();
};
function SomeComponent(props) {
const [text, setText] = useState('');
return (
<input type="text" onChange={onChange} value={transformText()} />
);
}
现在的问题是我需要将text
分别传递给transformText
和setText
给onChange
方法。我能想到的可能的解决方案是:
- 在组件函数中定义函数,并使用闭包来传递值。
- 在组件函数内,将值绑定(bind)到方法,然后使用绑定(bind)的方法。
执行其中任何一项操作都会更改对我需要维护的函数的常量引用,以免 input
组件重新呈现。我如何用钩子(Hook)做到这一点?有可能吗?
请注意,这是一个非常简化的人为示例。我的实际用例非常复杂,我绝对不想不必要地重新渲染组件。
编辑:
这不是 What useCallback do in React? 的副本因为我正在尝试弄清楚如何实现与过去在类组件方式中所做的类似的效果,而 useCallback
提供了一种的方式,它不是可维护性问题的理想选择。
最佳答案
在这里您可以 build your own hook (Dan Abramov 敦促不要使用术语“自定义 Hook ”,因为它使创建您自己的 Hook 变得比现在更难/更高级,这只是复制/粘贴您的逻辑)提取文本转换逻辑
只需从 Mohamed's answer 中“剪切”下面注释掉的代码.
function SomeComponent(props) {
// const [text, setText] = React.useState("");
// const onChange = ev => {
// setText(ev.target.value);
// };
// function transformText(text) {
// return text.toUpperCase();
// }
const { onChange, text } = useTransformedText();
return (
<input type="text" onChange={React.useCallback(onChange)} value={text} />
);
}
并将其粘贴到一个新函数中(按照惯例以“use*”为前缀)。 命名要返回的状态和回调(根据您的情况作为对象或数组)
function useTransformedText(textTransformer = text => text.toUpperCase()) {
const [text, setText] = React.useState("");
const onChange = ev => {
setText(ev.target.value);
};
return { onChange, text: textTransformer(text) };
}
由于可以传递转换逻辑(但默认使用大写),您可以使用自己的钩子(Hook)来使用共享逻辑。
function UpperCaseInput(props) {
const { onChange, text } = useTransformedText();
return (
<input type="text" onChange={React.useCallback(onChange)} value={text} />
);
}
function LowerCaseInput(props) {
const { onChange, text } = useTransformedText(text => text.toLowerCase());
return (
<input type="text" onChange={React.useCallback(onChange)} value={text} />
);
}
您可以像下面这样使用上面的组件。
function App() {
return (
<div className="App">
To Upper case: <UpperCaseInput />
<br />
To Lower case: <LowerCaseInput />
</div>
);
}
结果看起来像这样。
关于javascript - react Hook : accessing state across functions without changing event handler function references,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54597527/