天天看點

State與生命周期 (精讀React官方文檔—05)

這是我參與更文挑戰的第18天,活動詳情檢視: 更文挑戰

state是私有的。

官方描述:State 與 props 類似,但是 state 是私有的,并且完全受控于目前元件。

解讀

  • 官方對state的介紹很重要,我們必須要知道state是私有的,并且完全受控于目前元件。

将函數元件轉換為類元件

  1. 建立一個同名的類,并且繼承與React.Component.
  2. 添加一個空的render()方法.
  3. 将函數體(return(...))移動到render方法中.
  4. 在render方法中使用this.props代替props.
  5. 删除剩餘的空函數聲明.

函數元件

function Clock(props) {
    return (
        <div>
            <h1>Hello, world!</h1>
            <h2>It is {props.date.toLocaleTimeString()}.</h2>
        </div>
    );
}
複制代碼      

類元件

class Clock extends React.Component {
    render() {
        return (
            <div>
                <h1>Hello, world!</h1>
                <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
            </div>
        );
    }
}
複制代碼      
  • 每次更新的時候render函數都會被調用。

向類元件中添加局部state

  1. 将render方法中的this.props.data轉換為this.state.date.
  2. 給類添加一個構造函數,并為this.state指派.
  3. 移出類元素中的date屬性.

将聲明周期方法添加到類元件中

  • componentDidMount():元件挂載後開始運作,此處适合開啟定時器。
  • componentWillUnMount():元件将要解除安裝的時候運作,此處适合清除定時器。
  • 上面的這種方法叫做聲明周期方法。

使用類元件實作計時功能

class Clock extends React.Component {
    constructor(props) {
        super(props);
        this.state = {date: new Date()}
    }
    tick() {
        this.setState({
            date: new Date()
        })
    }
    componentDidMount() {
        this.timerID = setInterval(() => {
            this.tick();
        }, 1000);
    }
    componentWillUnmount() {
        clearInterval(this.timerID)
    }
    render() {
        return (
            <div>
                <h1>Hello, world!</h1>
                <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
            </div>
        );
    }
}
ReactDOM.render(
    <Clock />,
    document.getElementById('root')
);
複制代碼      

計時器的執行順序

  1. 當Clock元件傳遞給ReactDOM.reder後,React會首先調用Clock元件的構造函數,然後初始化state.
  2. React調用元件的render方法,然後更新DOM進行渲染。
  3. 當Clock的輸出被插入到DOM中後,開始調用componentDidMount這個生命周期函數,這個生命周期函數中,React向浏覽器設定一個定時器,每隔1秒,調用元件的tick方法。
  4. 浏覽器每調用一次tick方法,tick方法都會通過setState更新一次狀态,隻要狀态發生了改變,React就會重新調用元件的render方法,然後進行重新渲染,然後更新DOM。
  5. 一旦Clock元件從DOM中删除,React就會調用生命周期函數componentWillUnmount,然後清除定時器。

正确使用state

  1. 不要直接修改state,而是需要通過setState.
this.state.comment = 'Hello';  //不行
this.setState({comment: 'Hello'});  //可以
複制代碼      
  1. state的更新可能是異步的.
  • 下面的代碼可能無法更新state
// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});
複制代碼      
  • 解決上面的問題,可以讓state接收一個函數,這也是setState更新狀态的第二種方式。
// Correct
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));
複制代碼      
  1. state的更新會被合并。
看下面的例子你就明白了。
constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }
componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });
    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }
複制代碼      
官方解釋:this.setState({comments}) 完整保留了 this.state.posts, 但是完全替換了 this.state.comments。

這裡官方的解釋非常完善了。

資料是向下流動的

官方描述:元件可以選擇把它的 state 作為 props 向下傳遞到它的子元件中。FormattedDate 元件會在其 props 中接收參數 date,但是元件本身無法知道它是來自于 Clock 的 state,或是 Clock 的 props,還是手動輸入的。
<FormattedDate date={this.state.date} />
複制代碼      
function FormattedDate(props) {
  return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}
複制代碼      
  • 這種資料流就是單向資料流,因為state産生的資料隻能影響其子元件,
歡迎大家關注我的專欄,每日用碎片化的時間學習提高自己,加油!

繼續閱讀