Nice programing

React에서 컴포넌트간에 기능을 공유하는 올바른 방법

nicepro 2020. 12. 5. 10:38
반응형

React에서 컴포넌트간에 기능을 공유하는 올바른 방법


동일한 작업을 수행해야하는 여러 구성 요소가 있습니다. (자식 구성 요소를 매핑하고 각 구성 요소에 대해 작업을 수행하는 간단한 함수). 지금은 각 구성 요소에서이 방법을 정의하고 있습니다. 하지만 한 번만 정의하고 싶습니다.

최상위 구성 요소에서 정의한 다음 소품으로 전달할 수 있습니다. 그러나 그것은 옳지 않다. 소품보다 라이브러리 기능에 가깝습니다. (나에게 보인다).

이를 수행하는 올바른 방법은 무엇입니까?


browserify 와 같은 것을 사용 하면 일부 유틸리티 기능을 내보내는 외부 파일 즉 util.js를 사용할 수 있습니다.

var doSomething = function(num) {
 return num + 1;
}

exports.doSomething = doSomething;

그런 다음 필요에 따라 요청하십시오.

var doSomething = require('./util.js').doSomething;

최신 Javascript ES6 구문이있는 Utils.js

Utils.js여러 기능 등을 사용하여 이와 같은 파일을 만듭니다.

const someCommonValues = ['common', 'values'];

export const doSomethingWithInput = (theInput) => {
   //Do something with the input
   return theInput;
};

export const justAnAlert = () => {
   alert('hello');
};

그런 다음 util 함수를 사용하려는 구성 요소에서 필요한 특정 함수를 가져옵니다. 모든 것을 가져올 필요는 없습니다.

import {doSomethingWithInput, justAnAlert} from './path/to/utils.js/file'

그런 다음 다음과 같이 구성 요소 내에서 이러한 기능을 사용하십시오.

justAnAlert();
<p>{doSomethingWithInput('hello')}</p>

다음은 FetchUtil.handleErrorReact 컴포넌트 ( App) 에서 함수 ( )를 재사용하는 방법에 대한 몇 가지 예입니다 .

솔루션 1 : CommonJS 모듈 구문 사용

module.exports = {
  handleError: function(response) {
    if (!response.ok) throw new Error(response.statusText);
    return response;
  },
};

솔루션 2 : "createClass"사용 (React v16)

util / FetchUtil.js

const createReactClass = require('create-react-class');

const FetchUtil = createReactClass({
  statics: {
    handleError: function(response) {
      if (!response.ok) throw new Error(response.statusText);
      return response;
    },
  },
  render() {
  },
});

export default FetchUtil;

참고 : React v15.4 (또는 그 이하)를 사용하는 경우 createClass다음과 같이 가져와야 합니다.

import React from 'react';
const FetchUtil = React.createClass({});

출처 : https://reactjs.org/blog/2017/04/07/react-v15.5.0.html#migrating-from-reactcreateclass

구성 요소 (FetchUtil 재사용)

components / App.jsx

import Categories from './Categories.jsx';
import FetchUtil from '../utils/FetchUtil';
import Grid from 'material-ui/Grid';
import React from 'react';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {categories: []};
  }

  componentWillMount() {
    window
      .fetch('/rest/service/v1/categories')
      .then(FetchUtil.handleError)
      .then(response => response.json())
      .then(categories => this.setState({...this.state, categories}));
  }

  render() {
    return (
      <Grid container={true} spacing={16}>
        <Grid item={true} xs={12}>
          <Categories categories={this.state.categories} />
        </Grid>
      </Grid>
    );
  }
}

export default App;

Another solid option other than creating a util file would be to use a higher order component to create a withComponentMapper() wrapper. This component would take in a component as a parameter and return it back with the componentMapper() function passed down as a prop.

This is considered a good practice in React. You can find out how to do so in detail here.


If you want to manipulate state in helper functions follow this:

  1. Create a Helpers.js file:

    export function myFunc(){ return this.state.name; //define it according to your needs }

  2. Import helper function in your component file:

    import {myFunc} from 'path-to/Helpers.js'

  3. In your constructor add that helper function to the class

    constructor(){ this.myFunc = myFunc.bind(this) }

  4. In your render function use it:

    render(){ <div>{this.myFunc()}</div> }


Sounds like a utility function, in that case why not put it in a separate static utility module?

Otherwise if using a transpiler like Babel you can make use of es7's static methods:

class MyComponent extends React.Component {
  static someMethod() { ...

Or else if you are using React.createClass you can use the statics object:

var MyComponent = React.createClass({
  statics: {
    customMethod: function(foo) {
      return foo === 'bar';
    }
  }

However I don't advise those options, it doesn't make sense to include a component for a utility method.

Also you shouldn't be passing a method down through all your components as a prop it will tightly couple them and make refactoring more painful. I advise a plain old utility module.

The other option is to use a mixin to extend the class, but I don't recommend that as you can't do it in es6+ (and I don't see the benefit in this case).


It depends on how much the components' logic relate to each other.

If the logic is relatively-related (they only get used together in the same app), then you should share states between components. But if your logic is distantly-related (i.e., math util, text-formatting util), then you should make and import util class functions.

Relatively related components can be created with callback references, like this, in ./components/App.js...

<SomeItem
    ref={(instance) => {this.childA = instance}}
/>

<SomeOtherItem
    ref={(instance) => {this.childB = instance}}
/>

And then you can use shared functions between them like this...

this.childA.investigateComponent(this.childB);  // call childA function with childB as arg
this.childB.makeNotesOnComponent(this.childA);  // call childB function with childA as arg

Util-type components can be created like this, in ./utils/time.js...

export const getTimeDifference = function (start, end) {
    // return difference between start and end
}

And then they can be used like this, in ./components/App.js...

import React from 'react';
import {getTimeDifference} from './utils/time.js';

export default class App extends React.Component {
    someFunction() {
        console.log(getTimeDifference("19:00:00", "20:00:00"));
    }
}

Shouldn't you use a Mixin for this ? See https://facebook.github.io/react/docs/reusable-components.html

Although they are falling out of favour see https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750

Might be useful

참고URL : https://stackoverflow.com/questions/32888728/correct-way-to-share-functions-between-components-in-react

반응형