2017-05-28 36 views
0

學習React因此可能會有點難以解決的問題。考慮以下代碼:將行動綁定到純React狀態變化

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')); 

正如你可以看到目前點擊Container中的按鈕時,handleButtonToggle()被觸發從而改變按鈕本身的狀態,然後調用一個函數來改變父容器的狀態。這是React的方式嗎?此時,當功能handleButtonToggle被觸發時容器狀態被改變。理想情況下,我希望Container狀態直接依賴於MyButton 狀態(因爲將來可能會有方法設置按鈕狀態,而不是通過handleButtonToggle,而且我不想在每次狀態更改時手動調用this.props.handleToggle)。 。換句話說,當按鈕組件的狀態改變時,是否有辦法在按鈕組件中執行類似this.props.handleToggle(this.state.pressed)的操作。

Codepen

回答

1

您可以傳遞一個回調的第二個參數setState或您的組件上實現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組件是要使它成爲一個控制組件。如果容器組件需要保持按壓狀態,則受控按鈕組件將作爲道具從容器組件接收按下狀態。 Button組件的

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

而且渲染方法應該是:

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')); 

您需要這樣做,因爲您想共享兩個組件之間的狀態。這是documented here

我讓你看看codepen並詢問你的問題。 ;)

+0

初始化狀態這不是我所問的。 – redFur