2016-08-30 39 views
3

2つのReactコンポーネントを作成します。共通の機能を共有する必要があります。これらの関数はthis.setState()を使用しているので、ヘルパーファイルの中に入れられませんでした。私はcompositionを使ってみました。これにより、私は機能を共有することができますが、それらはまた状態を共有します。機能を共有しているが独立した状態の反応コンポーネントを作成するにはどうすればいいですか?

私は

//file 1 
var Component1 = React.createClass({ 
    getInitialState() { 
     return { 
      //return some common + new states 
     } 
}); 

//file 2 
var Component2 = React.createClass({ 
    getInitialState() { 
     return { 
      //return some common + new states 
     } 
}); 

// file 3 
// This file needs to have some functions, which can do: 
this.setState(); //on state of Component1 and Component2. 

答えて

1

ここには2つのオプションがあります。

これらのコンポーネントは、完全に独立している場合は、各コンポーネントが使用するデータを保持し、更新するために、ストアを使用し、店に購読することができます。これはFlux/Reduxパターンです。

コンポーネントは、ここで注意すべき事は店がコンポーネントの状態への直接アクセスを持っていないということである。この

class Component1 extends React.Component { 
    constructor(...props) { 
    super(...props) 
    this.update = this.update.bind(this) 
    this.state = { count: 0 } 
    } 

    update (storeData) { 
    this.setState(storeData) 
    } 

    componentDidMount() { 
    store.subscribe(this.update) 
    } 

    componentDidUnmount() { 
    store.unsubscribe(this.update) 
    } 

    render() { 
    return (<span>You have clicked {this.state.count} times</span>) 
    } 
} 

のように見えるかもしれません。コンポーネントがサブスクライブし、その他のメカニズムによってデータがパブリッシュされます。ストアは登録されたコールバックを呼び出します。これが発生します。 非常にシンプルな店がこの

const store = { 
    subscriptions: new Set(), 
    data: {}, 
    subscribe: function (callback) { 
    this.subscriptions.add(callback) 
    }, 
    unsubscribe: function (callback) { 
    this.subscriptions.delete(callback) 
    }, 
    update: function (key, value) { 
    this.data[key] = value 
    this.subscriptions.forEach(cb => cb(this.data)) 
    } 
} 

のようになります。これは、ストアへのアクセス権を持つ誰もが任意の/それに加入しているすべてのコンポーネントをアップデートすることができます。ここで

const CounterButton =() => (
    <button onClick={() => store.update('count', (store.data.count || 0) + 1)}>Increase Count</button> 
) 

は、あなたのコンポーネントが共有コンポーネントの両方の子である場合には、親が自分のpropsを更新するのではなく、自分を更新することによって、それらを更新することができ、この

親コンポーネント

を実証非常にcontrived codepenです状態。それは、それ自身の内部状態を使用してこれを追跡することができます。

class ParentComponent extends React.Component { 
    constructor(...props) { 
    super(...props) 
    this.state = { clicks: 0 } 
    } 

    render() { 
    return (
     <div> 
     <button onClick={() => this.setState({ clicks: this.state.clicks + 1})}>Increase Count</button> 
     <Component1 clicks={this.state.clicks} /> 
     <Component2 clicks={this.state.clicks} /> 
     </div> 
    ) 
    } 
} 
const Component1 = ({clicks}) => (
    <span>You have clicked {clicks} times</span> 
) 

const Component2 = (props) => (
    <span>You have pressed {props.clicks} times</span> 
) 

は、ここでは、この

何か他

非常識を実証equally contrived codepenである上記2行くための推奨方法です。しかしこれはJavaScriptであり、私たちはWild Westよりも少ないルールしか持っていません。あなたが実際に共有関数からコンポーネントの状態を直接制御したい場合は、何もあなたを止めることはありません。

var sharedComponents = new Set() 

function incrementComponents() { 
    sharedComponents.forEach(c => c.setState({clicks: c.state.clicks + 1})) 
} 

class Component1 extends React.Component { 
    constructor(...props) { 
    super(...props) 
    this.state = { clicks: 0 } 
    sharedComponents.add(this) 
    } 

    render() { 
    return (<span>You have clicked {this.state.clicks} times</span>) 
    } 
} 

setInterval(incrementComponents, 1000) 

ここにこれを示すcompletely insane codepenがあります。

+0

あなたの解決策は動作しますが、私はあなたのアプリケーションでreduxを使用していません。 全く別の場所でcomponent1とcomponent2を使用しようとしているため、この場合、2番目の解決策は機能しません。 私は現在この問題を解決するために 'mixins'を使用しています。私はそれが非推奨であることを知っていますが、高次コンポーネントを使用して同じものを作成することはできませんでした。 – aks

+0

私の最初の解決策はreduxを必要としません、reduxは単にパターンの成熟した実装です。私は完全に機能するマイクロストアを提供しました。これをコピー/貼り付けしてアプリで使用することができます。 – Tyrsius

+0

はいありがとう!理解するまでには時間がかかりました。 – aks

1

Parent component下の両方Component1 & Component2を維持し、あなたが子コンポーネントに親コンポーネントの機能を渡した場合、両方のComponent1 & Component2propsとしてParent Componentの機能を持つことになりますようなものが必要。したがって、parent-child relationshipの反応コンポーネントとしてこのように関数commonが得られます。子供は親からデータを得ることができます。このようにして、すべての子コンポーネントにも独自の状態があります。

+0

しかし、この親関数は子の状態を変更することができなければなりません。 状態に関連する共通の機能がたくさんあるので、私はこのようなものを使用しています。 – aks

関連する問題