admin管理员组文章数量:1287597
As far as I know, there are three ways to define functions in JavaScript.
1. Declaration
function handleEvent(e) {}
2. Assignment
var handleEvent = function(e) {}
3. Arrow
var handleEvent = (e) => {}
I have been searching for hours trying to find information on which of these options is the preferred way to declare handlers in functional React ponents. All the articles I found talk about class ponents, binding, etc. But with the new Hooks out, there must be standard for defining them inside the function as well. (After all, functional ponents have always existed anyway.)
Consider the following ponent, which declares three handlers, which are examples of different behaviour that you might need in a React ponent.
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>
);
}
All of these handlers are directly passed as callbacks into other ponents. They might be called whenever, but at that exact moment, we need to have access to the current values of props
and any state like inputName
. Additionally, as you might have noticed, the handleFormSubmit
handler also calls the resetForm
handler.
What would be the remended approach to defining the handlers from a performance perspective? Can it be avoidable that they are redefined on every render?
Does useCallback
also fit in here somewhere?
As far as I know, there are three ways to define functions in JavaScript.
1. Declaration
function handleEvent(e) {}
2. Assignment
var handleEvent = function(e) {}
3. Arrow
var handleEvent = (e) => {}
I have been searching for hours trying to find information on which of these options is the preferred way to declare handlers in functional React ponents. All the articles I found talk about class ponents, binding, etc. But with the new Hooks out, there must be standard for defining them inside the function as well. (After all, functional ponents have always existed anyway.)
Consider the following ponent, which declares three handlers, which are examples of different behaviour that you might need in a React ponent.
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>
);
}
All of these handlers are directly passed as callbacks into other ponents. They might be called whenever, but at that exact moment, we need to have access to the current values of props
and any state like inputName
. Additionally, as you might have noticed, the handleFormSubmit
handler also calls the resetForm
handler.
What would be the remended approach to defining the handlers from a performance perspective? Can it be avoidable that they are redefined on every render?
Does useCallback
also fit in here somewhere?
- What you have currently isnt valid javascript. If you intialize a const, you cant just define a function without first setting the const equal to something. – Cat_Enthusiast Commented Aug 3, 2019 at 9:30
- Ah thanks, it was a typo. – Snackoverflow Commented Aug 3, 2019 at 9:35
3 Answers
Reset to default 5The current standard is to declare the handlers as constants for immutability and as arrow-functions for binding purposes.
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>
);
}
All of these handlers are directly passed as callbacks into other ponents. They might be called whenever, but at that exact moment, we need to have access to the current values of props and any state like inputName
As currently constructed we meet the requirements for your description. Since props
and state
are defined as higher level data that the ponent has access to, all the event-handlers have access to them. And when used as a call-back in another ponent, they will remain bound to the initial ponent where they were defined in.
Which means if you have an event-handler like this:
const handleInputChange = (e) => {
setValue(e.target.value)
}
And you pass it into a ChildComponent like this:
<Child handleInputChange={handleInputChange}/>
And the Child uses the prop/event-handler like this:
<input onChange={props.handleInputChange}/>
You would be getting the event
from the Child input, but you would be updating the state
of the Parent, the original ponent that defined the event-handler.
There is virtually no difference between the "declaration", "assignment" and "arrow" approaches. The only thing that matters is that you don't always create new instances of the handler functions on each render. For this, use the useCallback
hook to memoize the function references:
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 e 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
docs: https://reactjs/docs/hooks-reference.html#usecallback
In functional ponent we don't need access to this
(even more - most linters will give you warning in such a case - and for a reason!). So it does not matter if we use arrow expression or declare a function.
But performance matters. Whatever option from your list you choose it will be recreated on each render. Declaring function itself is not really big deal but:
- passed down to child it may cause unnecessary re-rendering for PureComponent/
React.memo
-wrapped ponents. - May cause redundant run for
useMemo
/otheruseCallback
/useEffect
if later one includes your handler into dependencies list.
So either declare handler out of the ponent(once it does not rely on internal state at all) or use useCallback
. Beware it needs you explicitly list of all dependencies - don't ignore that. Otherwise result handler may operate on stale data.
本文标签: javascriptCorrect way to define handlers in functional React componentsStack Overflow
版权声明:本文标题:javascript - Correct way to define handlers in functional React components? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741312013a2371699.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论