-
使用
ReactDOM.render()
重复渲染function tick() { const element = ( <div> <h1>Hello, world!</h1> <h2>It is {new Date().toLocaleTimeString()}.</h2> </div> ); ReactDOM.render( element, document.getElementById('root') ); } setInterval(tick, 1000);
-
使用state管理状态
//创建一个同名的 ES6 class,并且继承于 React.Component class Clock extends React.Component { constructor(props) { super(props); this.state = { date: new Date() }; } //添加一个空的 render() 方法,将函数体移动到 render() 方法之中 render() { //在 render() 方法中使用 this.props 替换 props return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } //将生命周期方法添加到 Class 中 componentDidMount() {//在组件已经被渲染到 DOM 中后运行 this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } /** * 1.当 <Clock /> 被传给 ReactDOM.render()的时候,React 会调用 Clock 组件的构造函数。因为 Clock 需要显示当前的时间,所以它会用一个包含当前时间的对象来初始化 this.state。我们会在之后更新 state * 2.之后 React 会调用组件的 render() 方法。这就是 React 确定该在页面上展示什么的方式。然后 React 更新 DOM 来匹配 Clock 渲染的输出 * 3.当 Clock 的输出被插入到 DOM 中后,React 就会调用 ComponentDidMount() 生命周期方法。在这个方法中,Clock 组件向浏览器请求设置一个计时器来每秒调用一次组件的 tick() 方法 * 4.浏览器每秒都会调用一次 tick() 方法。 在这方法之中,Clock 组件会通过调用 setState() 来计划进行一次 UI 更新。得益于 setState() 的调用,React 能够知道 state 已经改变了,然后会重新调用 render() 方法来确定页面上该显示什么。这一次,render() 方法中的 this.state.date 就不一样了,如此以来就会渲染输出更新过的时间。React 也会相应的更新 DOM * 5.一旦 Clock 组件从 DOM 中被移除,React 就会调用 componentWillUnmount() 生命周期方法,这样计时器就停止了 */ } //============== ReactDOM.render( <Clock />, document.getElementById('root') )
-
使用 State规则
-
不要直接修改 State
//构造函数是唯一可以给 this.state 赋值的地方 constructor(props) { super(props); this.state = { date: new Date() }; } //使用this.setState更新this.state this.setState({ date: new Date() })
-
State 的更新可能是异步的:react 可能会把多个 setState() 调用合并成一个调用
//错误 this.setState({ counter: this.state.counter + this.props.increment, }); //正确写法 this.setState(function(state, props) { return { counter: state.counter + props.increment }; });
-
State 的更新会被合并:即可以使用
this.setState
单独更新各个变量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 }); }); }
-
-
数据是向下流动的
-
不管是父组件或是子组件都无法知道某个组件是有状态的还是无状态的,并且它们也并不关心它是函数组件还是 class 组件,除了拥有并设置了它的组件,其他组件都无法访问,组件可以选择把它的 state 作为 props 向下传递到它的子组件中
//普通 <h2>It is {this.state.date.toLocaleTimeString()}.</h2> //自定义组件 <FormattedDate date={this.state.date} /> function FormattedDate(props) { return <h2>It is {props.date.toLocaleTimeString()}.</h2>; }
-
每个组件都是真正独立的,任何的 state 总是所属于特定的组件,而且从该 state 派生的任何数据或 UI 只能影响树中“低于”它们的组件
class Clock extends React.Component { constructor(props) { super(props); this.state = { date: new Date() }; } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } } function App(){ return( <div> <Clock />, <Clock />, <Clock />, </div> ) } //============== ReactDOM.render( <App />, document.getElementById('root') )
-