- import React, { Component } from 'react'
-
- export default class LifeCycle extends Component {
- //// props = {age:10,name:'计数器'}
- static defaultProps = {
- name:'计数器'
- }
- constructor(props){
- //Must call super constructor in derived class before accessing 'this' or returning from derived constructor
- super();//this.props = props;
- this.state = {number:0,users:[]};//初始化默认的状态对象
- console.log('1. constructor 初始化 props and state');
-
- }
- //componentWillMount在渲染过程中可能会执行多次
- componentWillMount(){
- console.log('2. componentWillMount 组件将要挂载');
- //localStorage.get('userss');
- }
- //componentDidMount在渲染过程中永远只有执行一次
- //一般是在componentDidMount执行副作用,进行异步操作
- componentDidMount(){
- console.log('4. componentDidMount 组件挂载完成');
- fetch('https://api.github.com/users').then(res=>res.json()).then(users=>{
- console.log(users);
- this.setState({users});
- });
- }
- shouldComponentUpdate(nextProps,nextState){
- console.log('Counter',nextProps,nextState);
- console.log('5. shouldComponentUpdate 询问组件是否需要更新');
- return true;
- }
- componentWillUpdate(nextProps, nextState){
- console.log('6. componentWillUpdate 组件将要更新');
- }
- componentDidUpdate(prevProps, prevState)){
- console.log('7. componentDidUpdate 组件更新完毕');
- }
- add = ()=>{
- this.setState({number:this.state.number});
- };
- render() {
- console.log('3.render渲染,也就是挂载')
- return (
- <div style={{border:'5px solid red',padding:'5px'}}>
- <p>{this.props.name}:{this.state.number}</p>
- <button onClick={this.add}>+</button>
- <ul>
- {
- this.state.users.map(user=>(<li>{user.login}</li>))
- }
- </ul>
- {this.state.number%2==0&&<SubCounter number={this.state.number}/>}
- </div>
- )
- }
- }
- class SubCounter extends Component{
- constructor(props){
- super(props);
- this.state = {number:0};
- }
- componentWillUnmount(){
- console.log('SubCounter componentWillUnmount');
- }
- //调用此方法的时候会把新的属性对象和新的状态对象传过来
- shouldComponentUpdate(nextProps,nextState){
- console.log('SubCounter',nextProps,nextState);
- if(nextProps.number%3==0){
- return true;
- }else{
- return false;
- }
- }
- //componentWillReceiveProp 组件收到新的属性对象
- componentWillReceiveProps(){
- console.log('SubCounter 1.componentWillReceiveProps')
- }
- render(){
- console.log('SubCounter 2.render')
- return(
- <div style={{border:'5px solid green'}}>
- <p>{this.props.number}</p>
- </div>
- )
- }
- }
- import React from "react";
- import ReactDOM from "react-dom";
- import "./styles.css";
-
- function App() {
- return (
- <div className="App">
- <AAA />
- </div>
- );
- }
-
- class AAA extends React.Component {
- state = {
- age: 666
- };
-
- add = () => {
- this.setState({ age: this.state.age + 1 });
- };
-
- render() {
- return (
- <div>
- <ChildA onChangeParent={this.add} age={this.state.age} />
- </div>
- );
- }
- }
-
- class ChildA extends React.Component {
- state = {
- num: 888
- };
- // 根据新的属性对象派生状态对象
- // nextProps——新的属性对象 prevState——旧的状态对象
- static getDerivedStateFromProps(nextprops, state) {
- console.log('props',nextprops);
- // 返回一个对象来更新 state 或者返回 null 来表示接收到的 props 不需要更新 state
- if (nextprops.age !== state.age) {
- console.log("更新吧");
- return {
- onChangeParent:nextprops.onChangeParent,
- age: nextprops.age,
- // 注意:这里不需要把组件自身的状态也放进来
- // num:state.num
- };
- }
- return null;
- }
-
- add = () => {
- this.setState({ num: this.state.num + 1 });
- };
- render() {
- const { onChangeParent } = this.state;
- console.log('state',this.state);
- return (
- <>
- <div onClick={onChangeParent}>change</div>
- <div onClick={this.add}>add</div>
- </>
- );
- }
- }
-
- const rootElement = document.getElementById("root");
- ReactDOM.render(<App />, rootElement);
- import React, { Component } from "react";
- import ReactDOM from "react-dom";
-
- import "./styles.css";
-
- function App() {
- return (
- <div className="App">
- <GetSnapshotBeforeUpdate />
- </div>
- );
- }
-
- class GetSnapshotBeforeUpdate extends Component {
- constructor(props) {
- super(props);
- this.wrapper = React.createRef();
- this.state = { messages: [] };
- }
- componentDidMount() {
- setInterval(() => {
- this.setState({
- messages: ["msg:" + this.state.messages.length, ...this.state.messages]
- });
- //this.setState({messages:[...this.state.messages,this.state.messages.length]});
- }, 1000);
- }
- getSnapshotBeforeUpdate() {
- // 返回更新内容的高度 300px
- return this.wrapper.current.scrollHeight;
- }
- componentDidUpdate(prevProps, prevState, prevScrollHeight) {
- this.wrapper.current.scrollTop =
- this.wrapper.current.scrollTop +
- (this.wrapper.current.scrollHeight - prevScrollHeight);
- }
- render() {
- let style = {
- height: "100px",
- width: "200px",
- border: "1px solid red",
- overflow: "auto"
- };
- return (
- <ul style={style} ref={this.wrapper}>
- {this.state.messages.map((message, index) => (
- <li key={index}>{message}</li>
- ))}
- </ul>
- );
- }
- }
-
- const rootElement = document.getElementById("root");
- ReactDOM.render(<App />, rootElement);
- class ExampleComponent extends React.Component {
- state = {
- externalData: null,
- };
-
- componentDidMount() {
- this._loadAsyncData(this.props.id);
- }
-
- componentWillReceiveProps(nextProps) {
- // 当父组件的 props 改变时,重新请求数据
- if (nextProps.id !== this.props.id) {
- this.setState({externalData: null});
- this._loadAsyncData(nextProps.id);
- }
- }
-
- componentWillUnmount() {
- if (this._asyncRequest) {
- this._asyncRequest.cancel();
- }
- }
-
- render() {
- if (this.state.externalData === null) {
- // Render loading state ...
- } else {
- // Render real UI ...
- }
- }
-
- _loadAsyncData(id) {
- this._asyncRequest = asyncLoadData(id).then(
- externalData => {
- this._asyncRequest = null;
- this.setState({externalData});
- }
- );
- }
- }
- class ExampleComponent extends React.Component {
- state = {
- externalData: null,
- };
-
- static getDerivedStateFromProps(nextProps, prevState) {
- if (nextProps.id !== prevState.prevId) {
- return {
- externalData: null,
- prevId: nextProps.id,
- };
- }
- return null;
- }
-
- componentDidMount() {
- this._loadAsyncData(this.props.id);
- }
-
- // 借助 componentDidUpdate
- componentDidUpdate(prevProps, prevState) {
- if (this.state.externalData === null) {
- this._loadAsyncData(this.props.id);
- }
- }
-
- componentWillUnmount() {
- if (this._asyncRequest) {
- this._asyncRequest.cancel();
- }
- }
-
- render() {
- if (this.state.externalData === null) {
- // Render loading state ...
- } else {
- // Render real UI ...
- }
- }
-
- _loadAsyncData(id) {
- this._asyncRequest = asyncLoadData(id).then(
- externalData => {
- this._asyncRequest = null;
- this.setState({externalData});
- }
- );
- }
- }
- import React from "react";
- import ReactDOM from "react-dom";
-
- import "./styles.css";
-
- function App() {
- return (
- <div className="App">
- <AAA />
- </div>
- );
- }
-
- class AAA extends React.Component {
- state = {
- age: 66
- };
-
- add = () => {
- this.setState({ age: this.state.age + 1 });
- };
- render() {
- return (
- <div>
- <ChildA onChangeParent={this.add} age={this.state.age} />
- </div>
- );
- }
- }
-
- class ChildA extends React.Component {
- state = {
- num: 88
- };
-
- static getDerivedStateFromProps(nextProps, prevState) {
- if (nextProps.age !== prevState.age) {
- return {
- age: nextProps.age
- };
- }
- return null;
- }
-
- add = () => {
- this.setState({ num: this.state.num + 1 });
- };
-
- render() {
- const { onChangeParent } = this.props;
- console.log("render", this.state);
- return (
- <>
- <div onClick={onChangeParent}>change</div>
- <div onClick={this.add}>add</div>
- </>
- );
- }
- }
-
- const rootElement = document.getElementById("root");
- ReactDOM.render(<App />, rootElement);
- import React from "react";
- import ReactDOM from "react-dom";
-
- import "./styles.css";
-
- function App() {
- return (
- <div className="App">
- <AAA />
- </div>
- );
- }
-
- class AAA extends React.Component {
- state = {
- age: 66
- };
-
- add = () => {
- this.setState({ age: this.state.age + 1 });
- };
- render() {
- return (
- <div>
- <ChildA onChangeParent={this.add} age={this.state.age} />
- </div>
- );
- }
- }
-
- class ChildA extends React.Component {
- state = {
- num: 88,
- age: this.props.age
- };
-
- add = () => {
- this.setState({ num: this.state.num + 1 });
- };
-
- componentDidUpdate() {
- if (this.props.age !== this.state.age) {
- console.log("componentDidUpdate", this.props.age);
- this.setState({ age: this.props.age });
- }
- }
-
- render() {
- const { onChangeParent } = this.props;
- console.log("render", this.state);
- return (
- <>
- <div onClick={onChangeParent}>change</div>
- <div onClick={this.add}>add</div>
- </>
- );
- }
- }
-
- const rootElement = document.getElementById("root");
- ReactDOM.render(<App />, rootElement);
- class ExampleComponent extends React.Component {
- state = {
- id: '123456',
- };
- render(){
- const {id} = this.state;
- // 当 id 变化时,key 也随之改变,那么组件就会重新初始化
- return <ExampleComponent key={id} id={id}/>;
- }
- }
-
-
- class ExampleComponent extends React.Component {
- state = {
- externalData: null,
- };
- // 不需要使用 getDerivedStateFromProps 或者 componentWillReceiveProps
- // static getDerivedStateFromProps(nextProps, prevState) {
- // if (nextProps.id !== prevState.prevId) {
- // return {
- // externalData: null,
- // prevId: nextProps.id,
- // };
- // }
- // return null;
- // }
-
- componentDidMount() {
- this._loadAsyncData(this.props.id);
- }
-
- componentWillUnmount() {
- if (this._asyncRequest) {
- this._asyncRequest.cancel();
- }
- }
-
- render() {
- if (this.state.externalData === null) {
- // Render loading state ...
- } else {
- // Render real UI ...
- }
- }
-
- _loadAsyncData(id) {
- this._asyncRequest = asyncLoadData(id).then(
- externalData => {
- this._asyncRequest = null;
- this.setState({externalData});
- }
- );
- }
- }
- class AAA extends React.Component {
-
- static getDerivedStateFromProps(nextProps, prevState) {
- if (nextProps.id !== prevState.prevId) {
- const data = AAA.filterFn(nextProps.data);
- return {
- data,
- prevId: nextProps.id,
- };
- }
- return null;
- }
-
- static filterFn(data){
- // 过滤数据
-
- ...
-
- return newData;
- }
-
- ...
- }
- function filterFn(data){
- // 过滤数据
- ...
- return newData;
- }
-
-
- class AAA extends React.Component {
-
- static getDerivedStateFromProps(nextProps, prevState) {
- if (nextProps.id !== prevState.prevId) {
- const data = filterFn(nextProps.data);
- return {
- data,
- prevId: nextProps.id,
- };
- }
- return null;
- }
-
- ...
- }
- import React from "react";
- import ReactDOM from "react-dom";
-
- import "./styles.css";
-
- function App() {
- return (
- <div className="App">
- <AAA />
- </div>
- );
- }
-
- class AAA extends React.Component {
- state = {
- age: 66
- };
-
- add = () => {
- this.setState({ age: this.state.age + 1 });
- };
- render() {
- return (
- <div>
- <ChildA onChangeParent={this.add} age={this.state.age} />
- </div>
- );
- }
- }
-
- class ChildA extends React.Component {
- state = {
- num: 88
- };
- static getDerivedStateFromProps(nextprops, state) {
- console.log("getDerivedStateFromProps", nextprops);
- if (nextprops.age !== state.age) {
- return {
- // 给一个标识
- status: false,
- // age: nextprops.age,
- onChangeParent: nextprops.onChangeParent
- };
- }
- return null;
- }
-
- add = () => {
- this.setState({ num: this.state.num + 1 });
- };
-
-
- processData(){
- console.log("process",this.props);
- return this.props.age;
- }
-
- componentDidUpdate() {
- // 根据标识来更新状态
- if (!this.state.status) {
- this.setState({
- age: this.processData(),
- status: true
- });
- console.log("componentDidUpdate");
- }
- }
- componentDidMount() {
- this.setState({
- age: this.props.age,
- status: true
- });
- }
-
- render() {
- const { onChangeParent } = this.state;
- console.log("render", this.state);
- return (
- <>
- <div onClick={onChangeParent}>change</div>
- <div onClick={this.add}>add</div>
- </>
- );
- }
- }
-
- const rootElement = document.getElementById("root");
- ReactDOM.render(<App />, rootElement);
- class AAA extends React.Component {
- // 必须给 state 设置一个值,哪怕是一个空对象
- state = {
- num:666
- };
- static getDerivedStateFromProps(nextProps, prevState) {
- if (nextProps.id !== prevState.prevId) {
- return {
- data:nextProps.data,
- prevId: nextProps.id,
- // 只需要映射属性,不需要把组件自身的状态也加进去
- // num:prevState.num
- };
- }
- return null;
- }
-
- ...
- }
- import React, {Component} from 'react'
-
- export default class LifeCycle extends Component {
- static defaultProps = {
- name: '计数器'
- };
-
- constructor(props) {
- super(props);
- this.state = {number: 0};//初始化默认的状态对象
- console.log('1. constructor 初始化 props and state');
- }
-
- componentWillMount() {
- console.log('2. componentWillMount 组件将要挂载');
- }
-
- componentDidMount() {
- console.log('4. componentDidMount 组件挂载完成');
- }
-
- shouldComponentUpdate(nextProps, nextState) {
- console.log('Counter', nextProps, nextState);
- console.log('5. shouldComponentUpdate 询问组件是否需要更新');
- return true;
- }
-
- componentWillUpdate() {
- console.log('6. componentWillUpdate 组件将要更新');
- }
-
- componentDidUpdate() {
- console.log('7. componentDidUpdate 组件更新完毕');
- }
-
- add = () => {
- this.setState({number: this.state.number });
- };
-
- render() {
- console.log('3.render渲染')
- return (
- <div style={{border: '5px solid red', padding: '5px'}}>
- <p>{this.state.number}</p>
- <button onClick={this.add}>+</button>
- </div>
- )
- }
- }
由于 React 未来的版本中推出了异步渲染,在 dom 被挂载之前的阶段都可以被打断重来,导致 componentWillMount、componentWillUpdate、componentWillReceiveProps 在一次更新中可能会被触发多次,因此那些只希望触发一次的副作用应该放在 componentDidMount 中
最常见的误解就是 getDerivedStateFromProps 和 componentWillReceiveProps 只会在 props “改变”时才会调用。实际上只要父组件重新渲染时,这两个生命周期函数就会重新调用,不管 props 有没有“变化”