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


90

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

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

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


이 링크를 확인하십시오 . 또는 Google에서 "mixins"및 "HOC"를 검색하십시오.
Borzh

답변:


36

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

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

exports.doSomething = doSomething;

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

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

@AnkitSinghaniya 그에 따라 앱의 프런트 엔드 상태를 관리하기 위해 무엇을 사용하고 있습니까?
deowk

1
반응 상태를 사용하고 있습니다.
aks aks

내가 'doSomething'을 얻는 이유는 어떤 아이디어도 정의되지 않았습니까?
Abhijit Chakra

45

최신 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>

/file수입 라인의 끝은 무엇입니까 ?
alex

@alex 그것은 단지 예일뿐입니다. 거기에
util.js

13

도우미 함수에서 상태를 조작하려면 다음을 따르십시오.

  1. Helpers.js 파일을 만듭니다.

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

  2. 구성 요소 파일에서 도우미 함수를 가져옵니다.

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

  3. 생성자에서 해당 도우미 함수를 클래스에 추가하십시오.

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

  4. 렌더링 기능에서 다음을 사용하십시오.

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


10

다음은 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;

7

util 파일을 만드는 것 이외의 또 다른 확실한 옵션은 상위 구성 요소를 사용하여 withComponentMapper()래퍼 를 만드는 것 입니다. 이 구성 요소는 구성 요소를 매개 변수로 가져 와서 componentMapper()소품으로 전달 된 함수 와 함께 다시 반환합니다 .

이것은 React에서 좋은 관행으로 간주됩니다. 여기에서 자세한 방법을 확인할 수 있습니다.


왜 React가 withComponent 패턴이 비슷한 것처럼 보이는 컴포넌트 상속을 권장하지 않는지 궁금합니다.
workwise

@Wor 사용 상속은 두 개의 구성 요소를 의미
제이크

4

유틸리티 함수처럼 들리는데,이 경우 별도의 정적 유틸리티 모듈에 넣는 것이 어떻습니까?

그렇지 않으면 Babel과 같은 트랜스 파일러를 사용하는 경우 es7의 정적 메서드를 사용할 수 있습니다.

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

아니면 React.createClass를 사용하는 경우 다른 사람이 사용할 수있는 정적은 객체 :

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

그러나 이러한 옵션을 권장하지 않으며 유틸리티 메서드에 대한 구성 요소를 포함하는 것은 의미가 없습니다.

또한 모든 구성 요소에 메서드를 전달하면 안됩니다. 평범한 오래된 유틸리티 모듈을 권장합니다.

다른 옵션은 믹스 인을 사용하여 클래스를 확장하는 것이지만 es6 +에서는 할 수 없기 때문에 권장하지 않습니다 (이 경우 이점이 보이지 않음).


믹스 인에 대한 정보가 유용합니다. 이 경우 수명주기 이벤트에서 자동으로 발생하는 것보다 함수를 조건부로 사용하고 싶습니다. 그래서. 당신이 말했듯이 평범한 오래된 유틸리티 함수가 갈 길입니다.

1
참고 : React.createClass는 React 15.5.0부터 더 이상 사용되지 않습니다. create-react-app는 create-react-class대신 npm 모듈 사용을 제안합니다 .
Alex Johnson

OP와 똑같은 일을하려고하는데 여기서 조금 혼란 스럽습니다. 나열한 옵션은 권장하지 않습니다. 당신 무엇 을 추천합니까?
kkuilla

예를 들어 함수에 대한 파일을 만들 doSomething.js거나 예를 들어 유사한 "유틸리티"함수가 여러 개있는 파일을 utils.js만들고 필요한 곳에 해당 함수를 가져옵니다.
Dominic

4

아래에 두 가지 스타일을 보여줄 것이며 구성 요소의 논리가 서로 얼마나 관련되어 있는지에 따라 선택하고 싶을 것입니다.

스타일 1- 이와 같이 콜백 참조를 사용하여 상대적으로 관련된 구성 요소만들 수 있습니다 ./components/App.js.

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

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

그리고 다음 과 같이 그들 사이에 공유 기능을 사용할있습니다 .

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

스타일 2-유틸리티 유형 구성 요소 는 다음 과 같이 만들 수 있습니다 ./utils/time.js.

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

그리고 그들은 다음 과 같이 사용할 수 있습니다 ./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"));
    }
}

어느 것을 사용해야합니까?

논리가 상대적으로 관련이 있는 경우 (동일한 앱에서만 함께 사용됨) 구성 요소간에 상태를 공유해야합니다. 그러나 논리가 멀리 관련되어있는 경우 (예 : math util, text-formatting util) util 클래스 함수를 만들고 가져와야합니다.


2

이것을 위해 Mixin을 사용해야하지 않습니까? 참조 https://facebook.github.io/react/docs/reusable-components.html를

그들이 호의적으로 떨어지고 있지만 https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750을 참조 하십시오.

유용 할 수 있음


나는 mixin이 일반적인 기능을 내보내는 것보다 더 나은 해결책이라는 데 동의합니다.
Tao Huang

@TaoHuang 고려해야 할 몇 가지 사항, 1. Mixins는 미래의 증거가 아니며 최신 앱에서 점점 더 적게 사용됩니다. 2. 내 보낸 함수를 사용하면 코드 프레임 워크에 구애받지 않고 다른 js 프로젝트에서 이러한 함수를 쉽게 사용할 수 있습니다. 또한 Mixins를 사용하지 않는 이유에 대한이 게시물을 읽으십시오-> facebook.github.io/react/blog/2016/07/13/…
deowk

믹스 인은 상태에 액세스하고 수정할 수 있지만 트레이 트는 그렇지 않으며 OP가 함수 라이브러리로 처리 할 무언가를 원하기 때문에 믹스 인은 올바른 솔루션이 아닙니다.
HoldOffHunger

이를 업데이트하려면 고차 함수를 사용하십시오. facebook.github.io/react/docs/higher-order-components.html
Davet

첫 번째 링크가 끊어졌습니다
alex
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.