据我所知,有三种方法可以在JavaScript中定义函数。
1。声明
function handleEvent(e) {}
2。分配
var handleEvent = function(e) {}
3。箭头
var handleEvent = (e) => {}
我已经花了数小时试图寻找信息,以了解在功能性React组件中声明处理程序的首选方式。我发现的所有文章都涉及类组件,绑定等。但是,在新的Hooks发布之后,还必须有在函数内部定义它们的标准。 (毕竟,功能组件始终存在。)
考虑以下组件,该组件声明三个处理程序,这些示例是您在React组件中可能需要的不同行为的示例。
function NameForm(props) {
const [inputName, setInputName] = useState("");
useEffect(() => setInputName(props.initialValue), [props.initialValue]);
const handleInputChange = function(event) {
setInputName(event.target.value);
};
const resetForm = function() {
setInputName(props.initialValue);
props.onReset();
};
const handleFormSubmit = function(event) {
event.preventDefault();
props.onSubmit(inputName);
resetForm();
};
/* React-Bootstrap simple form example using these handlers. */
return (
<Form onSubmit={handleFormSubmit}>
<Form.Group controlId="NameForm">
<Form.Control
type="text"
placeholder="Enter your name here"
value={inputName}
onChange={handleInputChange}
/>
<Button type="submit">Submit</Button>
<Button onClick={resetForm}>Reset</Button>
</Form.Group>
</Form>
);
}
所有这些处理程序都直接作为回调传递给其他组件。它们可能会在任何时候被调用,但是在那一刻,我们需要访问props
的 current 值和inputName
之类的任何状态。此外,您可能已经注意到,handleFormSubmit
处理程序还调用resetForm
处理程序。
从性能的角度来看,定义处理程序的推荐方法是什么?是否可以避免在每个渲染器上都重新定义它们?
useCallback
也适合放在这里吗?
答案 0 :(得分:2)
当前的标准是将处理程序声明为不可变的常量,并声明为绑定目的的箭头函数。
function NameForm(props) {
const [inputName, setInputName] = useState("");
useEffect(() => setInputName(props.initialValue), [props.initialValue]);
const handleInputChange = (event) => {
setInputName(event.target.value);
}
const resetForm = () => {
setInputName(props.initialValue);
props.onReset();
}
const handleFormSubmit = (event) => {
event.preventDefault();
props.onSubmit(inputName);
resetForm();
}
/* React-Bootstrap simple form example using these handlers. */
return (
<Form onSubmit={handleFormSubmit}>
<Form.Group controlId="NameForm">
<Form.Control
type="text"
placeholder="Enter your name here"
value={inputName}
onChange={handleInputChange}
/>
<Button type="submit">Submit</Button>
<Button onClick={resetForm}>Reset</Button>
</Form.Group>
</Form>
);
}
所有这些处理程序都直接作为回调传递给其他处理程序 组件。他们可能会在任何时候被调用,但是在那一刻, 我们需要访问道具的当前值和任何状态 像inputName
按照目前的构造,我们满足您描述的要求。由于props
和state
被定义为组件可以访问的高级数据,因此所有事件处理程序都可以访问它们。并且当在另一个组件中用作回调时,它们将保持绑定到定义它们的初始组件。
这意味着您是否具有这样的事件处理程序:
const handleInputChange = (e) => {
setValue(e.target.value)
}
然后将其传递给子组件,如下所示:
<Child handleInputChange={handleInputChange}/>
孩子使用prop / event-handler像这样:
<input onChange={props.handleInputChange}/>
您将从子项输入中获取event
,但是将更新父级的state
,父项是定义事件处理程序的原始组件。
答案 1 :(得分:2)
“声明”,“分配”和“箭头”方法之间几乎没有区别。唯一重要的是,您不必总是在每个渲染器上创建处理程序函数的新实例。为此,请使用useCallback
挂钩来记住函数引用:
const handleInputChange = useCallback((event) => {
setInputName(event.target.value);
}, []); // `setInputName` is guaranteed to be unique, from the React Hooks docs, so no need to pass it as a dependency
const resetForm = useCallback(() => {
setInputName(props.initialValue);
props.onReset();
}, [props.onReset, props.initialValue]; // these come from props, so we don't know if they're unique => need to be passed as dependencies
const handleFormSubmit = useCallback((event) => {
event.preventDefault();
props.onSubmit(inputName);
resetForm();
}, [props.onSubmit, resetForm, inputName]); // `resetForm` and `inputName`, although defined locally, will change between renders, so we also need to pass them as dependencies
useCallback
文档:https://reactjs.org/docs/hooks-reference.html#usecallback
答案 2 :(得分:0)
在功能组件中,我们不需要访问this
(甚至更多-在这种情况下,大多数短毛猫都会向您发出警告-并且是有原因的!)。因此,无论我们使用箭头表达式还是声明函数都没有关系。
但是性能很重要。您从列表中选择的任何选项都会在每个渲染器上重新创建。声明函数本身并不是什么大问题,但是:
React.memo
包装的组件。useMemo
/其他useCallback
/ useEffect
的处理程序添加到依赖项列表中,可能会导致多余的运行。所以要么在组件之外声明处理程序(一旦它完全不依赖内部状态),要么使用useCallback
。注意,它需要您明确列出所有依赖项-不要忽略它。否则结果处理程序可能会对过时的数据进行操作。