Saya memiliki banyak komponen yang semuanya perlu melakukan hal yang sama. (Fungsi sederhana yang memetakan komponen anak mereka dan melakukan sesuatu untuk masing-masing komponen). Saat ini saya sedang mendefinisikan metode ini di setiap komponen. Tapi saya hanya ingin mendefinisikannya sekali.
Saya bisa mendefinisikannya di komponen tingkat atas dan kemudian menyebarkannya sebagai penyangga. Tapi rasanya kurang tepat. Ini lebih merupakan fungsi perpustakaan daripada prop. (Menurut saya).
Apa cara yang benar untuk melakukan ini?
Jawaban:
Jika Anda menggunakan sesuatu seperti browserify maka Anda dapat memiliki file eksternal yaitu util.js yang mengekspor beberapa fungsi utilitas.
var doSomething = function(num) { return num + 1; } exports.doSomething = doSomething;
Kemudian membutuhkannya sesuai kebutuhan
var doSomething = require('./util.js').doSomething;
sumber
Utils.js dengan sintaks Javascript ES6 terbaru
Buat
Utils.js
file seperti ini dengan banyak fungsi, dllconst someCommonValues = ['common', 'values']; export const doSomethingWithInput = (theInput) => { //Do something with the input return theInput; }; export const justAnAlert = () => { alert('hello'); };
Kemudian di komponen Anda yang ingin Anda gunakan fungsi util, impor fungsi spesifik yang diperlukan. Anda tidak perlu mengimpor semuanya
import {doSomethingWithInput, justAnAlert} from './path/to/utils.js/file'
Dan kemudian gunakan fungsi-fungsi ini di dalam komponen seperti ini:
justAnAlert(); <p>{doSomethingWithInput('hello')}</p>
sumber
/file
di akhir baris impor?Jika Anda ingin memanipulasi status dalam fungsi pembantu ikuti ini:
Buat file Helpers.js:
export function myFunc(){ return this.state.name; //define it according to your needs }
Impor fungsi pembantu di file komponen Anda:
import {myFunc} from 'path-to/Helpers.js'
Dalam konstruktor Anda, tambahkan fungsi pembantu itu ke kelas
constructor(){ this.myFunc = myFunc.bind(this) }
Dalam fungsi render Anda, gunakan:
render(){ <div>{this.myFunc()}</div> }
sumber
Berikut adalah beberapa contoh bagaimana Anda dapat menggunakan kembali fungsi (
FetchUtil.handleError
) dalam komponen React (App
).Solusi 1: Menggunakan sintaks modul CommonJS
module.exports = { handleError: function(response) { if (!response.ok) throw new Error(response.statusText); return response; }, };
Solusi 2: Menggunakan "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;
Catatan: Jika Anda menggunakan React v15.4 (atau lebih rendah), Anda perlu mengimpor
createClass
sebagai berikut:import React from 'react'; const FetchUtil = React.createClass({});
Sumber: https://reactjs.org/blog/2017/04/07/react-v15.5.0.html#migrating-from-reactcreateclass
Komponen (yang menggunakan kembali FetchUtil)
komponen / 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;
sumber
Opsi lain yang solid selain membuat file util adalah menggunakan komponen orde tinggi untuk membuat
withComponentMapper()
pembungkus. Komponen ini akan mengambil komponen sebagai parameter dan mengembalikannya dengancomponentMapper()
fungsi yang diturunkan sebagai prop.Ini dianggap sebagai praktik yang baik di React. Anda dapat mengetahui cara melakukannya secara detail di sini.
sumber
Kedengarannya seperti fungsi utilitas, dalam hal ini mengapa tidak meletakkannya di modul utilitas statis terpisah?
Jika tidak, jika menggunakan transpiler seperti Babel Anda dapat menggunakan metode statis es7:
class MyComponent extends React.Component { static someMethod() { ...
Atau jika Anda menggunakan React.createClass Anda dapat menggunakan objek statik :
var MyComponent = React.createClass({ statics: { customMethod: function(foo) { return foo === 'bar'; } }
Namun saya tidak menyarankan opsi tersebut, tidak masuk akal untuk menyertakan komponen untuk metode utilitas.
Anda juga tidak boleh melewatkan metode melalui semua komponen Anda sebagai penyangga, itu akan memasangkannya dengan erat dan membuat refactoring lebih menyakitkan. Saya menyarankan modul utilitas lama biasa.
Pilihan lainnya adalah menggunakan mixin untuk memperluas kelas, tetapi saya tidak menyarankan itu karena Anda tidak dapat melakukannya di es6 + (dan saya tidak melihat manfaatnya dalam kasus ini).
sumber
React.createClass
tidak digunakan lagi sejak React 15.5.0. create-react-app menyarankan penggunaan modul npmcreate-react-class
sebagai gantinya.doSomething.js
, atau file dengan beberapa fungsi "utilitas" yang serupa misalnyautils.js
dan mengimpor fungsi-fungsi tersebut di mana Anda perlu menggunakannyaSaya akan menunjukkan dua gaya di bawah ini, dan Anda akan ingin memilih tergantung pada seberapa banyak logika komponen berhubungan satu sama lain.
Gaya 1 - Komponen yang relatif terkait dapat dibuat dengan referensi callback, seperti ini, di
./components/App.js
...<SomeItem ref={(instance) => {this.childA = instance}} /> <SomeOtherItem ref={(instance) => {this.childB = instance}} />
Dan kemudian Anda dapat menggunakan fungsi bersama di antara mereka seperti ini ...
this.childA.investigateComponent(this.childB); // call childA function with childB as arg this.childB.makeNotesOnComponent(this.childA); // call childB function with childA as arg
Gaya 2 - Komponen tipe utilitas dapat dibuat seperti ini, di
./utils/time.js
...export const getTimeDifference = function (start, end) { // return difference between start and end }
Dan kemudian mereka bisa digunakan seperti ini, di
./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")); } }
Yang harus digunakan?
Jika logikanya relatif terkait (hanya digunakan bersama dalam aplikasi yang sama), Anda harus berbagi status antar komponen. Tetapi jika logika Anda berhubungan jauh (mis., Math util, text-formatting util), maka Anda harus membuat dan mengimpor fungsi kelas util.
sumber
Bukankah Anda harus menggunakan Mixin untuk ini? Lihat https://facebook.github.io/react/docs/reusable-components.html
Meskipun mereka tidak disukai, lihat https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
Semoga bermanfaat
sumber