[reactjs] 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>


답변

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

  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>
    }


답변

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


답변

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

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


답변

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

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

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

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

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

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

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

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


답변

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

스타일 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 클래스 함수를 만들고 가져와야합니다.