React'teki bileşenler arasında işlevleri paylaşmanın doğru yolu


92

Hepsinin aynı şeyi yapması gereken birden fazla bileşene sahibim. (Alt bileşenlerini eşleyen ve her birine bir şeyler yapan basit bir işlev). Şu anda bu yöntemi bileşenlerin her birinde tanımlıyorum. Ama onu sadece bir kez tanımlamak istiyorum.

Bunu en üst düzey bileşende tanımlayabilir ve ardından bir destek olarak aktarabilirim. Ancak bu pek doğru gelmiyor. Bir proptan çok bir kütüphane işlevidir. (Bana öyle görünüyor ki).

Bunu yapmanın doğru yolu nedir?


Bu bağlantıya göz atın . Veya google'da "mixins" ve "HOC" araması yapın.
Borzh

Yanıtlar:


38

Browsererify gibi bir şey kullanırsanız, bazı yardımcı fonksiyon fonksiyonlarını dışa aktaran bir harici dosyaya, yani util.js'ye sahip olabilirsiniz.

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

exports.doSomething = doSomething;

O zaman gerektiği gibi isteyin

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

@AnkitSinghaniya Uygulamanızın ön uç durumunu yönetmek için ne kullanıyorsunuz?
deowk

1
React durumlarını kullanıyorum.
aks

Neden 'doSomething' alıyorum hiçbir fikrim yok tanımlanmadı?
Abhijit Chakra

48

En son Javascript ES6 sözdizimi ile Utils.js

Utils.jsDosyayı birden çok işlevle, vb. Oluşturun

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

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

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

Ardından, yararlan işlevlerini kullanmak istediğiniz bileşenlerinizde, gerekli olan belirli işlevleri içe aktarın. Her şeyi içe aktarmanıza gerek yok

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

Ve sonra bu işlevleri bileşende şu şekilde kullanın:

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

1
/fileİthalat satırının sonunda ne için var?
alex

@alex Bu sadece bir örnek. Göreli yolunuzu util.js'ye koyun
Fangming

14

Yardımcı işlevlerde durumu değiştirmek istiyorsanız, şunu izleyin:

  1. Helpers.js dosyası oluşturun:

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

  2. Yardımcı işlevi bileşen dosyanıza içe aktarın:

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

  3. Yapıcınızda bu yardımcı işlevi sınıfa ekleyin

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

  4. Oluşturma işlevinizde kullanın:

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


10

FetchUtil.handleErrorBir React component ( App) içindeki bir fonksiyonu ( ) nasıl yeniden kullanabileceğinize dair bazı örnekler aşağıda verilmiştir .

1.Çözüm: CommonJS modülü sözdizimini kullanma

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

2.Çözüm: "createClass" kullanımı (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;

Not: React v15.4 (veya altı) kullanıyorsanız createClass, aşağıdaki şekilde içe aktarmanız gerekir :

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

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

Bileşen (FetchUtil'i yeniden kullanır)

bileşenler / 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

Bir kullanım dosyası oluşturmaktan başka bir katı seçenek, bir withComponentMapper()sarmalayıcı oluşturmak için daha yüksek bir bileşen kullanmaktır . Bu bileşen bir bileşeni parametre olarak alır ve onu componentMapper()bir destek olarak aktarılan fonksiyonla geri döndürür .

Bu, React'te iyi bir uygulama olarak kabul edilir. Bunun nasıl yapılacağını ayrıntılı olarak buradan öğrenebilirsiniz.


WithComponent modelinin benzer göründüğü durumlarda React'in bileşen kalıtımını neden caydırdığını merak ediyorum?
19:42

@Wor Kalıtımı kullanmak iki bileşen anlamına gelir
Jake

4

Bir yardımcı program işlevi gibi geliyor, bu durumda neden onu ayrı bir statik yardımcı program modülüne koymuyorsunuz?

Aksi takdirde, Babel gibi bir aktarıcı kullanıyorsanız, es7'nin statik yöntemlerinden yararlanabilirsiniz:

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

Veya React.createClass kullanıyorsanız statics nesnesini kullanabilirsiniz :

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

Bununla birlikte, bu seçenekleri önermiyorum, bir yardımcı yöntem için bir bileşen eklemek mantıklı değil.

Ayrıca, bir destek olarak tüm bileşenlerinizden bir yöntem geçirmemelisiniz, bu onları sıkıca birleştirecek ve yeniden düzenlemeyi daha acı verici hale getirecektir. Sade, eski bir yardımcı program modülü öneririm.

Diğer seçenek, sınıfı genişletmek için bir mixin kullanmaktır, ancak bunu es6 + 'da yapamayacağınız için tavsiye etmiyorum (ve bu durumda faydasını görmüyorum).


Karışımlar hakkındaki bilgiler faydalıdır. Bu durumda, bir yaşam döngüsü olayında otomatik olarak bir şey olmasını sağlamak yerine, işlevi koşullu olarak kullanmak istiyorum. Yani. Dediğiniz gibi, eski bir yardımcı program işlevi gitmenin yoludur.

1
Not: React.createClassReact 15.5.0'dan beri kullanımdan kaldırılmıştır. create-react-app create-react-classbunun yerine npm modülünün kullanılmasını önerir .
Alex Johnson

OP ile aynı şeyi yapmak istiyorum ama burada biraz kafam karıştı. Listelediğiniz seçeneklerden hiçbirini önermiyorsunuz. Ne mi önerirsiniz?
kkuilla

Basitçe işlev için bir dosya hazırlardım doSomething.js, ya da birden çok benzer "yardımcı" işlevli bir dosya, örneğin utils.jsve bunları kullanmanız gereken yerlerde bu işlevleri içe
Dominic

4

Aşağıda iki stil göstereceğim ve bileşenlerin mantığının birbiriyle ne kadar ilişkili olduğuna bağlı olarak seçim yapmak isteyeceksiniz.

Stil 1 - Göreceli olarak ilgili bileşenler , bunun gibi geri arama referanslarıyla oluşturulabilir./components/App.js ...

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

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

Ve sonra aralarında şu şekilde paylaşılan işlevleri kullanabilirsiniz ...

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

Stil 2 - Yardımcı tip bileşenler şu şekilde oluşturulabilir : ./utils/time.js...

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

Ve sonra da olabilir kullanılan içinde, böyle ./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"));
    }
}

Hangisini kullanmalı?

Mantık göreceli olarak ilişkiliyse (yalnızca aynı uygulamada birlikte kullanılırlar), o zaman bileşenler arasında durumları paylaşmalısınız. Ancak mantığınız uzaktan ilişkili ise (yani, matematik kullanım, metin biçimlendirme kullanım), o zaman faydalan sınıf işlevlerini yapmalı ve içe aktarmalısınız.


2

Mixin'in burada ortak bir işlevi dışa aktarmaktan daha iyi bir çözüm olduğuna katılıyorum.
Tao Huang

@TaoHuang Dikkate alınması gereken bazı şeyler, 1. Miksler geleceğe uygun değildir ve modern uygulamalarda gittikçe daha az kullanılacaktır, 2. Dışa aktarılan bir işlevi kullanmak kod çerçevenizi agnostik yapar - bu işlevi başka herhangi bir js projesinde kolayca kullanabilirsiniz. Ayrıca lütfen
Mixins'i

Bir özellik olmasa da bir mixin duruma erişebilir ve durumu değiştirebilir ve OP, bir şeyin bir işlev kitaplığı olarak ele alınmasını istediğini söylediği için, bir mixin doğru çözüm olmayacaktır.
HoldOffHunger

Bunu güncellemek için daha yüksek dereceli işlevleri kullanın. facebook.github.io/react/docs/higher-order-components.html
Davet

İlk bağlantı
alex
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.