React三大核心属性和生命周期(持续更新)

发布时间:2024年01月20日

本文用来记录我的React学习过程,借鉴了很多大佬的文章,收获不少,如果有不对的地方,请大家指正😊!

三大核心属性

1.state

组件通常需要根据交互更改屏幕上显示的内容。输入表单应该更新输入字段,单击轮播图上的“下一个”应该更改显示的图片,单击“购买”应该将商品放入购物车。组件需要“记住”某些东西:当前输入值、当前图片、购物车。在 React 中,这种组件特有的记忆被称为 state。
直接上代码:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);

  function handleClick() {
    setIndex(index + 1);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

在 React 中,useState 以及任何其他以“use”开头的函数都被称为 Hook。

Hook 是特殊的函数,只在 React 渲染时有效。

2.props

React 组件使用 props 来互相通信。每个父组件都可以提供 props 给它的子组件,从而将一些信息传递给它。Props 可能会让你想起 HTML 属性,但你可以通过它们传递任何 JavaScript 值,包括对象、数组和函数。
这里主要展示一下父组件向子组件传值

父组件Profile

export default function Profile() {
  return (
    <Avatar
      person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
      size={100}
    />
  );
}

子组件Avatar

function Avatar({ person, size }) {
  return (
    <img
      className="avatar"
      src={getImageUrl(person)}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

3.refs

使用 ref 操作 DOM
获取指向节点的 ref
要访问由 React 管理的 DOM 节点,首先,引入 useRef Hook:

import { useRef } from 'react';

然后,在你的组件中使用它声明一个 ref:

const myRef = useRef(null);

最后,将 ref 作为 ref 属性值传递给想要获取的 DOM 节点的 JSX 标签:

<div ref={myRef}>

useRef Hook 返回一个对象,该对象有一个名为 current 的属性。最初,myRef.current 是 null。当 React 为这个

创建一个 DOM 节点时,React 会把对该节点的引用放入 myRef.current。然后,你可以从 事件处理器 访问此 DOM 节点,并使用在其上定义的内置浏览器 API。

// 你可以使用任意浏览器 API,例如:

myRef.current.scrollIntoView();

这里的 ref 指向一个数字,但是,像 state 一样,你可以让它指向任何东西:字符串、对象,甚至是函数。与 state 不同的是,ref 是一个普通的 JavaScript 对象,具有可以被读取和修改的 current 属性。

请注意,组件不会在每次递增时重新渲染。 与 state 一样,React 会在每次重新渲染之间保留 ref。但是,设置 state 会重新渲染组件,更改 ref 不会!
在这里插入图片描述
stste和refs的比较

staterefs
useRef(initialValue)返回 { current: initialValue }useState(initialValue) 返回 state 变量的当前值和一个 state 设置函数 ( [value, setValue])
更改时不会触发重新渲染更改时触发重新渲染
可变 —— 你可以在渲染过程之外修改和更新 current 的值“不可变” —— 你必须使用 state 设置函数来修改 state 变量,从而排队重新渲染
你不应在渲染期间读取(或写入) current 值你可以随时读取 state。但是,每次渲染都有自己不变的 state 快照

生命周期(旧与新)

新旧生命周期区别

旧版
在这里插入图片描述
挂载阶段
constructor
componentWillMount
render
componentDidMount

更新阶段
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate

卸载阶段
componentWillUnmount

新版
在这里插入图片描述
挂载阶段
constructor
getDerivedStateFromProps
render
componentDidMount

更新阶段

getDerivedStateFromProps
shouldComponentUpdate
render
getSnapshotBeforeUpdate
componentDidUpdate

卸载阶段
componentWillUnmount

各个钩子函数作用(旧)

1.constructor()

构造函数,通常用于初始化组件的状态和绑定方法

constructor(props) { 
    super(props);
    this.state = { count: 0 }; 
    this.handleClick = this.handleClick.bind(this); 
}

补充:
.bind()方法: Function.prototype.bind()方法创建一个新的函数,当这个新函数被调用时,它的this值会被设置为提供的值,并且其参数也会被预先设定。

2.render()

用来返回组件的UI结构,它是一个纯函数,其中不应该包含任何副作用或改变状态的操作。

import React,{Component} from 'react'

export default class Hello extends Component{
	render(){
		return <h2>Hello,React!</h2>
	}
}

3.componentDidMount()

这个函数是在组件挂载到DOM后执行的,可以在这里获取数据、进行一些异步请求或DOM操作。

componentDidMount() { 
    // 发起API请求或其他初始化操作 
    fetchData().then(data => { 
        this.setState({ data 
        }); 
    }); 
}

4.shouldComponentUpdate()

这个函数是用来判断组件是否需要重新渲染,返回一个布尔值,可以优化性能。

shouldComponentUpdate(nextProps, nextState) {
    // 这里假设props有一个min属性,表示计数器的最小值
    if (nextProps.min !== undefined && nextState.count < nextProps.min) {
      return false;
    }
    return true;
  }

注意:此钩子函数有个setState(),在组件中,每当调用this.setState()方法时,就会触发shouldComponentUpdate(),如果函数返回true就更新状态,否则不更新。

5.forceUpdate()

强制更新
当调用forceUpdate()时,会直接来到componentWillUpdate()钩子函数。
何时使用: 只想更新一下组件,但是不想对状态作出任何的更改,就可以调用,通过this.forceUpdate()直接调用

6.componentDidUpdate()

componentDidUpdate(prevProps, prevState):组件更新后触发,用于处理更新后的操作。

componentDidUpdate(prevProps, prevState) {
    console.log('组件已更新完毕');
    if (prevProps.id !== this.props.id) { 
        // 处理props变化的逻辑 
        console.log('props.id变了');
    } 
}

7.componentWillUnmount()

componentWillUnmount():这个函数是在组件卸载前执行的,可以在这里进行一些清理工作,比如取消订阅、清除定时器、取消异步请求或移除事件监听器等。

各个钩子函数作用(新)

1.与旧版发生变化的生命周期钩子函数

componentDidUpdate()
componentDidUpdate(prevProps,prevState,snapshot):它在组件更新(即render() 方法执行后)后被调用。它接收三个参数:prevProps、prevState、snapshot。与旧的钩子函数相比,多了一个参数snapshot。

componentDidUpdate(prevProps, prevState, snapshot) {
    if (this.props.data !== prevProps.data) {
      console.log('this.props中的数据变了');
    }

    // 使用getSnapshotBeforeUpdate()的返回值
    if (snapshot !== null) {
      console.log('Snapshot from getSnapshotBeforeUpdate:', snapshot);
    }
}

注意:如果getSnapshotBeforeUpdate()有返回值,它会成为componentDidUpdate()的第三个参数,你可以在这里使用它。

2.比旧版新增的生命周期钩子函数:

getDerivedStateFromProps()

getDerivedStateFromProps(nextProps,prevState):是一个静态方法,用于在组件接收新的props时计算并返回新的state。这个方法在React 16.3版本之后引入,用来替代不推荐使用的componentWillReceiveProps()方法。

class MyComponent extends React.Component { 
    static getDerivedStateFromProps(nextProps, prevState) { 
        // 根据 nextProps 和 prevState 计算并返回新的 state 
        if (nextProps.value !== prevState.value) { 
            return { value: nextProps.value }; 
        } 
        return null; // 如果不需要更新 state,返回 null 
    } 
    
    constructor(props) { 
        super(props); 
        this.state = { 
            value: props.value, 
        }; 
    }
    
    render() { 
        return <div>{this.state.value}</div>; 
    } 
}

以下是getDerivedStateFromProps() 的主要特点和使用方式:

静态方法:getDerivedStateFromProps() 是一个静态方法,因此不能访问实例的this,它只接收两个参数:nextProps 和 prevState。
计算新的state:通常,你可以在这个方法内部根据nextProps 和 prevState 来计算并返回新的state。这个新的state将在组件更新时应用。
不触发副作用:与componentDidUpdate() 不同,getDerivedStateFromProps() 不应执行副作用,如发起网络请求。它只用于计算state。
适用于控制组件内部状态:getDerivedStateFromProps() 主要用于控制组件内部的状态,以确保它与外部传入的props保持同步。

getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate(nextProps,prevState):它在组件更新(即将应用新props或state并重新渲染)之前触发。它允许你捕获组件更新前的一些信息,并在组件更新后使用这些信息。

class MyComponent extends React.Component {
	constructor(props) {
	  super(props);
	  this.myRef = React.createRef();
	}
  
	getSnapshotBeforeUpdate(prevProps, prevState) {
	  // 捕获组件更新前的滚动位置
	  if (prevProps.items.length < this.props.items.length) {
		const scrollHeight = this.myRef.current.scrollHeight;
		const scrollTop = this.myRef.current.scrollTop;
		return { scrollHeight, scrollTop };
	  }
	  return null;
	}
  
	componentDidUpdate(prevProps, prevState, snapshot) {
	  // 使用snapshot来恢复滚动位置
	  if (snapshot !== null) {
		this.myRef.current.scrollTop = snapshot.scrollTop + (this.myRef.current.scrollHeight - snapshot.scrollHeight);
	  }
	}
  
	render() {
	  // 使用ref来获取DOM元素的引用
	  return <div ref={this.myRef}>{/* 组件内容 */}</div>;
	}
}

在本示例中,getSnapshotBeforeUpdate() 用于捕获滚动位置,然后在componentDidUpdate() 中使用snapshot来恢复滚动位置,以确保用户在滚动列表时不会在更新后失去滚动位置。

以下是关于getSnapshotBeforeUpdate() 的主要特点和用法:

触发时机:getSnapshotBeforeUpdate() 在render() 方法被调用后、组件DOM更新前触发,通常用于在更新前捕获一些DOM信息。
接收两个参数:这个生命周期方法接收两个参数:prevProps、prevState。你可以使用这些参数来比较前后的props和state。
返回值:getSnapshotBeforeUpdate()
方法应该返回一个值(通常是一个对象),它将成为componentDidUpdate()
方法的第三个参数。这个返回值通常用于保存一些DOM相关的信息,比如滚动位置。
通常和componentDidUpdate()一起使用:getSnapshotBeforeUpdate()
结合componentDidUpdate(prevProps, prevState, snapshot)
使用,snapshot参数是getSnapshotBeforeUpdate() 的返回值。你可以在componentDidUpdate()
中使用snapshot来执行DOM操作或其他一些操作。

本文参考链接linklink

文章来源:https://blog.csdn.net/ZTBztb123456/article/details/135609988
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。