Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to declare auxiliar functions for a React functional component. Inside or outside?

I'm building a <BasicForm> component that will be used to build forms inside my application. It should handle submit, validation and also should keep track of the inputs state (like touched, dirty, etc).

Therefore, it needs some functions to do all that and I've been wondering what is the best place to put those declarations (concerning code organization and performance optimization, considering React and JavaScript best practices).

I'm using React 16.8 hooks and bundling with Webpack.

So far, here's what I've got:

BasicForm.js

/* I moved those validating functions to a different file
because I thought they are helpers and not directly related 
to my BasicForm functionality */

import { validateText, validatePassword, validateEmail } from './Parts/ValidationHelpers';

function BasicForm(props) {

  const [inputs, setInputs] = useState({});
  const [isSubmitting, setIsSubmitting] = useState(false);

  // These are functions to handle these events
  function onChange(event) {...}
  function onBlur(event) {...}
  function onFocus(event) {...}

  // This function creates the initial state for each form input
  function setInputInitialState(inputProps) {...}

  // This functions does what it name says
  function validateAllFields() {...}

  // This one also
  function checkValidationAndSubmit() {...}

  return(
    <FormContext.Provider value={{
      onBlur: onBlur,
      onFocus: onFocus,
      onChange: onChange,
      inputs: inputs,
      setInputInitialState: setInputInitialState
    }}>
      <form onSubmit={onSubmit} method='POST' noValidate>
        {props.children}
      </form>
    </FormContext.Provider>
  );

}

My question is: as you can see, up to this point, I'm declaring all the functions that my <BasicForm> uses (onChange, onBlur, onFocus, setInputInitialState, validateAllFields, checkValidationAndSubmit) inside the body of my BasicForm React component function.

Is this the best practice? If I was using classes those functions would probably be methods of my BasicForm class. But since I changed to hooks and got rid of most classes, I always have doubts about placing auxiliar functions inside or outside my React components function's body. Is there a best practice for this?

When the auxiliar function may need some variables or state from my main function, I could always pass them as parameters when I call them (if they are declared outside).

Do I gain or lose anything if I declare them outside of my BasicForm function? Keeping in mind that this is a module that gets bundled with Webpack.

like image 264
cbdeveloper Avatar asked Mar 25 '19 14:03

cbdeveloper


People also ask

Can we define function inside functional component React?

In React we can simply define a component using a function that returns an HTML-like syntax. React Hooks enables us to define state into such functional components.

Where should functions in function components go?

In most cases you should declare the functions outside the component function so you declare them only once and always reuse the same reference. When you declare the function inside, every time the component is rendered the function will be defined again.

Can hooks be used outside components?

"Hooks can only be called inside the body of a function component." This is a common warning that developers run into when starting out with hooks in React.

How do you put a function inside JSX?

This can be done by importing the function into App. js file and using the name of the function as a custom JSX tag.


1 Answers

If the function does not rely on props or state, then it is best to define it outside of your component function. If it does rely on props or state, then it generally makes sense to define it inside your component function, but if you are passing the function as a prop to a child component, then you should consider using useCallback (though this generally only adds value if the child component is memoized).

When the function depends on props or state, if you move the function out of the component and pass it arguments, you will end up needing to wrap that call in another function (e.g. ()=>helperFunc(prop1, someState)) in order to pass it as a prop to a child component. If the function is large, you may still want to pull it out of the component in that manner, but that just comes down to style preferences.

For more information on useCallback, see my answer here: Trouble with simple example of React Hooks useCallback

like image 189
Ryan Cogswell Avatar answered Oct 04 '22 17:10

Ryan Cogswell