2017-05-28 3 views
0

学習リアクトは少しノービーな質問かもしれません。このコードを考えてみましょう:コンテナ内のボタンがhandleButtonToggle()をクリックしたときにあなたが現在見ることができるように純粋なリアクトの状態変化にアクションを結びつける

class Application extends React.Component { 
    render() { 
    return <Container /> 
    } 
} 

class Container extends React.Component { 
    constructor(props) { 
    super(props) 
    this.state = { 
     isOn: false 
    } 
    this.handleToggle = this.handleToggle.bind(this); 
    } 

    handleToggle(on) { 
    this.setState({ 
     isOn: on 
    }); 
    } 

    render() { 
    return ( 
     <div> 
     <p> 
     {this.state.isOn ? 'on' : 'off'} 
     </p> 
     <MyButton handleToggle={this.handleToggle} /> 
     </div> 
    ); 
    } 
} 


class MyButton extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     pressed: false 
    } 
    this.handleButtonToggle = this.handleButtonToggle.bind(this); 
    } 


    handleButtonToggle() { 
    const on = !this.state.pressed 
    this.setState({ 
     pressed: on 
    }); 
    this.props.handleToggle(on); 
    } 

    render() { 
    return (
     <div> 
     <button onClick={this.handleButtonToggle}> 
      {this.state.pressed ? "pressed" : "depressed"} 
     </button> 
     </div> 
    ); 
    } 
} 

ReactDOM.render(<Application />, document.getElementById('app')); 

は、ボタン自体の状態を変更して、親コンテナの状態を変更する関数を呼び出す発射されます。これはそれを行うための反作法ですか?現時点では、コンテナの状態は、handleButtonToggle関数が起動されたときに変更されます。理想的には、Containerの状態をMyButton の状態に直接依存させたいと考えています(将来はボタンの状態をhandleButtonToggle以外に設定する方法があり、状態が変わるたびに手動でthis.props.handleToggleを呼び出す必要はありません)。 。言い換えれば、状態が変化したときにボタンコンポーネントにthis.props.handleToggle(this.state.pressed)のような何かをする方法があります。

Codepen

答えて

1

あなたはsetStateに2番目の引数としてコールバックを渡すことができますいずれか、または状態変化を待つためにあなたのコンポーネントにcomponentDidUpdateを実装します。最小の変更は、元のようになります。

handleButtonToggle() { 
    const on = !this.state.pressed 
    this.setState({ 
    pressed: on 
    },() => { 
    this.props.handleToggle(on); 
    }); 
} 

またはcomponentDidUpdateと:

componentDidUpdate(prevProps, prevState) { 
    if (prevState.on !== this.state.on) { 
    this.props.handleToggle(this.state.on); 
    } 
} 
+0

後者のバージョンは、私が探しているもののようです! – redFur

2

コードを確認した後、Buttonコンポーネントを記述するためのより良い方法は、それを制御コンポーネントにすることです。コンテナコンポーネントが押された状態を維持する必要がある場合、制御されるボタンコンポーネントは、押された状態を、コンテナコンポーネントから支柱として受け取ることになる。

<MyButton pressed={this.state.pressed} onToggle={this.handleToggle} /> 

とButtonコンポーネントのrenderメソッドは次のようになります。

render() { 
    return (
     <div> 
     <button onClick={this.props.onToggle}> 
      {this.props.pressed ? "pressed" : "depressed"} 
     </button> 
     </div> 
    ); 
    } 

実際のボタンのトグルは、コンテナコンポーネントのhandleToggle方法で行われます。ここでは

handleButtonToggle() { 
    let { pressed } = this.state; 
    pressed = !pressed; 
    this.setState({ 
     pressed 
    }); 
    } 
+0

私もこのバージョンを検討していました。なぜあなたはそれが良いと言いますか?これは、ボタンの状態がコンテナの状態をより直接的に反映するためですか? – redFur

+1

親コンポーネントによって状態を維持する必要がある場合は、このバージョンが優れています。しかし、汎用コンポーネントが必要な場合は、制御された(押された)と制御されていない(defaultPressed)の両方を許可することは良い選択です。 – vijayst

+0

はい私はそれ自身でのみ状態を設定できる汎用ボタンが必要です。 – redFur

-1

です作業コード:https://codepen.io/damien-monni/pen/XRwewV。 本当に必要な変更に集中できるように、できる限り多くのコードを保存しようとしました。

controlled componentを作成する必要があります。ボタンの状態はコンテナに保存され、子のMyButtonコンポーネントに渡されます。

/* 
* A simple React component 
*/ 
class Application extends React.Component { 
    render() { 
    return <Container /> 
    } 
} 

class Container extends React.Component { 
    constructor(props) { 
    super(props) 
    this.state = { 
     isOn: false 
    } 
    this.handleToggle = this.handleToggle.bind(this); 
    } 

    handleToggle() { 
    this.setState({ 
     isOn: !this.state.isOn 
    }); 
    } 

    render() { 
    return ( 
     <div> 
     <p> 
     {this.state.isOn ? 'on' : 'off'} 
     </p> 
     <MyButton pressed={this.state.isOn} handleToggle={this.handleToggle} /> 
     </div> 
    ); 
    } 
} 


class MyButton extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     pressed: this.props.pressed 
    } 
    this.handleButtonToggle = this.handleButtonToggle.bind(this); 
    } 


    handleButtonToggle() { 
    this.props.handleToggle(); 
    } 

    componentWillReceiveProps(nextProps) { 
    if (nextProps.pressed !== this.props.pressed) { 
     this.setState({ pressed: nextProps.pressed }); 
    } 
    } 

    render() { 
    return (
     <div> 
     <button onClick={this.handleButtonToggle}> 
      {this.state.pressed ? "pressed" : "depressed"} 
     </button> 
     </div> 
    ); 
    } 
} 


/* 
* Render the above component into the div#app 
*/ 

ReactDOM.render(<Application />, document.getElementById('app')); 

2つのコンポーネント間で状態を共有したいからです。これはdocumented hereです。

私はあなたがcodepenを見て、あなたの質問をします。 ;)

+0

を使用して状態を初期化します。これは私が求めていることではありません。 – redFur

関連する問題