mitmath514
mitmath514

Reputation: 427

React sharing method across components

I have a component that looks like this so far:

import React from 'react';

// Import images
import logo from '../images/logo-small.png';

class LoginForm extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            email: '',
            password: '',
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(e) {
        const target = e.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        this.setState({
            [name]: value
        });
    }

I'm going to be reusing the same handleChange(e) method across multiple components across multiple files on my app. Is there a way I can separate out this method instead of having to rewrite it each time?

Would I put handleChange(e) into a file names utils.js and import that file each time I need to use it? If so, how do I make sure that this.setState works properly?

I have some rough ideas on how to go about this (such as the one above), but I want to take the best approach to this. Thanks!

Upvotes: 5

Views: 6333

Answers (4)

Ivaylo Atanasov
Ivaylo Atanasov

Reputation: 225

Hooks are another way to go.

With custom hooks you can reuse your state dependent handlers with ease between components.

// hooks.js
const { useState } from 'react';

const useHandleChange = () => {
  const [formValues, setFormValues] = useState({});

  const handleChange = (e) => {
    let { type, checked, name, value} = e.target;
    value = type === 'checkbox' ? checked : value;

    setFormValues({
      [name]: value
    });
  };

  return { formValues, handleChange };
}

// Component.js
import useHandleChange from './hooks';

const LoginForm = () => {
  // you can use that on each component that needs the handleChange function
  const { formValues, handleChange } = useHandleChange();

  return (
    // html template
  );
};

You would need to convert your component to function component, though so I would propose this solution only if it doesn't require too much effort to refactor your code. Hooks does not work on class components.

Upvotes: 9

x-magix
x-magix

Reputation: 2860

I guess simply create new file for example utils.js and export your functions from it as below

const handleChange = (e) => {
        const target = e.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        return { [name]: value }
}

export.handler = handleChange;

than import it in your file, for example like this:

const utils = require('path/to/file');

setState(utils.handleChange(e));

happy codding !

Upvotes: 1

Michalis Garganourakis
Michalis Garganourakis

Reputation: 2930

Of course. What you are looking for is called Higher-Order Components

You can create a HOC with all the methods/logic you need to share across, and wrap the components you need to enhance with it.

Upvotes: 1

Ed Lucas
Ed Lucas

Reputation: 7355

You certainly could create a helper function. However, it's nice to have your setState() in the component that holds the state.

To that end, you could do something like this:

// utils.js helper function
handleCheckbox(e) {
  const target = e.target,
        value = target.type === 'checkbox' ? target.checked : target.value;
  return {name: target.name, value: value};
}


// In your component
handleChange(e) {
  // Destructured in case you need to handle it differently
  const { name, value } = handleCheckbox(e);
  this.setState({[name]: value});
}

The helper could pass {[name]: value}, but it shouldn't necessarily be concerned with how the variables are finally used.

Upvotes: 0

Related Questions