In functional component 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:

  1. passed down to child it may cause unnecessary re-rendering for PureComponent/React.memo-wrapped components.
  2. May cause redundant run for useMemo/other useCallback/useEffect if later one includes your handler into dependencies list.

So either declare handler out of the component(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.


The 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) => {

    const resetForm = () => {

    const handleFormSubmit = (event) => {

    /* React-Bootstrap simple form example using these handlers. */
    return (
        <Form onSubmit={handleFormSubmit}>
            <Form.Group controlId="NameForm">
                    placeholder="Enter your name here"
                <Button type="submit">Submit</Button>
                <Button onClick={resetForm}>Reset</Button>

All of these handlers are directly passed as callbacks into other components. 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 component has access to, all the event-handlers have access to them. And when used as a call-back in another component, they will remain bound to the initial component where they were defined in.

Which means if you have an event-handler like this:

const handleInputChange = (e) => {

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 component 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` is guaranteed to be unique, from the React Hooks docs, so no need to pass it as a dependency

const resetForm = useCallback(() => {
}, [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) => {
}, [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:

Related Query

More Query from same tag