私はすべて同じことをする必要がある複数のコンポーネントを持っています。(子コンポーネントにマップし、それぞれに何かを行う単純な関数)。現時点では、各コンポーネントでこのメソッドを定義しています。しかし、私はそれを一度だけ定義したいと思います。
トップレベルのコンポーネントで定義して、小道具として渡すことができます。しかし、それは完全に正しく感じられません。これは、小道具というよりもライブラリ関数です。(私にはそう思われる)。
これを行う正しい方法は何ですか?
私はすべて同じことをする必要がある複数のコンポーネントを持っています。(子コンポーネントにマップし、それぞれに何かを行う単純な関数)。現時点では、各コンポーネントでこのメソッドを定義しています。しかし、私はそれを一度だけ定義したいと思います。
トップレベルのコンポーネントで定義して、小道具として渡すことができます。しかし、それは完全に正しく感じられません。これは、小道具というよりもライブラリ関数です。(私にはそう思われる)。
これを行う正しい方法は何ですか?
回答:
browserifyのようなものを使用する場合は、いくつかのユーティリティ関数をエクスポートするutil.jsなどの外部ファイルを作成できます。
var doSomething = function(num) {
return num + 1;
}
exports.doSomething = doSomething;
次に、必要に応じてそれを要求します
var doSomething = require('./util.js').doSomething;
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
インポート行の最後には何がありますか?
ヘルパー関数で状態を操作する場合は、次の手順に従ってください。
Helpers.jsファイルを作成します。
export function myFunc(){
return this.state.name; //define it according to your needs
}
コンポーネントファイルにヘルパー関数をインポートします。
import {myFunc} from 'path-to/Helpers.js'
コンストラクターで、そのヘルパー関数をクラスに追加します
constructor(){
this.myFunc = myFunc.bind(this)
}
レンダリング関数でそれを使用します:
render(){
<div>{this.myFunc()}</div>
}
FetchUtil.handleError
Reactコンポーネント(App
)で関数()を再利用する方法の例をいくつか示します。
module.exports = {
handleError: function(response) {
if (!response.ok) throw new Error(response.statusText);
return response;
},
};
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
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ファイルの作成以外のもう1つの確実なオプションは、高次のコンポーネントを使用してwithComponentMapper()
ラッパーを作成することです。このコンポーネントは、コンポーネントをパラメーターとして受け取り、componentMapper()
関数が小道具として渡された状態でそれを返します。
これはReactでは良い習慣と考えられています。その方法について詳しくは、こちらをご覧ください。
ユーティリティ関数のように聞こえますが、その場合は、別の静的ユーティリティモジュールに入れてみませんか?
それ以外の場合、Babelのようなトランスパイラーを使用する場合は、es7の静的メソッドを利用できます。
class MyComponent extends React.Component {
static someMethod() { ...
または、React.createClassを使用している場合は、staticsオブジェクトを使用できます。
var MyComponent = React.createClass({
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
}
ただし、これらのオプションはお勧めしません。ユーティリティメソッドのコンポーネントを含めることは意味がありません。
また、メソッドを小道具としてすべてのコンポーネントに渡すことはできません。メソッドはコンポーネントを緊密に結合し、リファクタリングをより苦痛にします。昔ながらのユーティリティモジュールをお勧めします。
もう1つのオプションは、ミックスインを使用してクラスを拡張することですが、es6 +では実行できないため、お勧めしません(この場合、メリットはわかりません)。
React.createClass
React15.5.0以降は非推奨です。create-react-appは、create-react-class
代わりにnpmモジュールの使用を提案しています。
doSomething.js
、関数のファイル、または複数の同様の「ユーティリティ」関数を含むファイルを作成し、utils.js
それらを使用する必要がある場所にインポートします
以下に2つのスタイルを示しますが、コンポーネントのロジックが相互にどの程度関連しているかに応じて選択する必要があります。
スタイル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 - Utilのタイプのコンポーネントをすることができます作成には、次のように./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クラス関数を作成してインポートする必要があります。
これにMixinを使用するべきではありませんか?https://facebook.github.io/react/docs/reusable-components.htmlを参照してください
彼らは支持を失っていますが、https: //medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750を参照してください
役に立つかもしれません