首页 - 通讯 - React数据管理的setState和Props

React数据管理的setState和Props

2023-10-10 16:20

setState调用原理

setState是React中用于更新组件状态的方法。其调用原理可以分为以下几个步骤:

  1. 状态改变:当调用setState时,React会将新的状态对象与当前状态对象合并(合并过程是浅合并)。 React 不会直接修改当前的状态对象,而是创建一个新的状态对象来保证状态不被直接修改,从而遵循了 React 的不变性原则。

  2. 触发重新渲染 :状态更新完成后,React 会调用组件的 render 方法重新渲染组件。在重新渲染的过程中,React会生成一棵新的虚拟DOM树(Virtual DOM)。

  3. 虚拟 DOM 比较 :React 会将新生成的虚拟 DOM 树与之前的虚拟 DOM 树进行比较,找出两者之间的差异(所谓的变更集)。

  4. 部分更新:React 将变更集中的差异应用到实际 DOM 中以更新用户界面。这是一个高效的过程,因为 React 只更新需要更新的部分,而不是重新渲染整个页面。

    ?元素引用或执行副作用操作。

需要注意的是,由于setState是异步的,React可能会将多个setState合并到一个更新中以提高性能。这意味着在函数内多次调用setState可能不会导致多次重新渲染,而是一次性状态更新并在函数执行结束后重新渲染。

例如,以下代码中的多个 setState 调用合并为单个更新:

这个.setState({计数: 这个.状态计数 + 1 });
这个.setState({ 计数: 这个.状态

此功能有时会导致不直观的行为,因此可以使用函数式 setState 形式来确保状态更新基于先前的状态并且不受合并的影响:

这个.setState((prevState)=> ({ 计数:上一个状态.计数+1}));

setState第二个参数

this.setState(newState, 回调);

  • newState是描述要更新的状态的对象或函数。这可以是新的状态值,也可以是接受先前状态作为参数并返回新状态的函数。
  • callback是一个可选的回调函数,将在状态更新完成后调用。

例如:

导入反应,{组件} 来自 '反应'; 计数器 扩展 组件  {构造函数(道具){超级(道具);这个.状态= {计数: 0,};}手柄增量 = ()  =>{这个.setState({计数 这个 .状态计数+1},()=>  {//回调函数,会在状态更新后被调用console.log('更新计数:',  这个.状态.计数 ;});}渲染() {返回 (< div><p >计数{这个状态计数}</p><按钮点击={这个.手柄增量}>增量</按钮></div>);}}

在上面的示例中,当单击按钮并调用 handleIncrement 方法时,this.setState 用于递增 count 的值。回调函数通过状态更新后调用的console.log输出更新后的count值。

回调函数的主要用途包括:

  • 执行状态更新后需要立即执行的代码。
  • 执行副作用操作,例如发出网络请求或操作 DOM。
  • 状态更新后通知其他组件或触发其他操作。

道具和状态的区别

props(属性)和state(状态)是React中用于管理组件数据的两个不同概念。它们有以下主要区别:

  1. 来源

    • props:是父组件传递给子组件的数据。父组件通过属性(props)将数据传递给子组件。子组件不能直接修改这些数据,它们是只读的。
    • state:是组件内部维护的数据,用于描述组件的具体状态。组件可以管理和修改自己的状态。
  2. 可变性

    • props:不可变,子组件不能直接修改从父组件接收到的 props。 Props 用于从外部向组件传递信息。组件应该将 props 视为只读数据。
    • state:它是可变的,组件可以通过调用setState方法来更新其状态。
  3. 管理

    • props:由父组件管理和传递,子组件只能访问和使用props。
    • state:由组件自己管理和维护,组件可以在需要的时候修改自己的状态。
  4. 功能

    • props:用于向子组件传递数据,以控制子组件的行为和显示。
    • state:用于管理组件的内部状态,以响应用户交互、数据请求或其他事件。
  5. 通过

    • props:通过组件的属性(props)传递给子组件。父组件可以通过属性控制子组件的行为。
    • state:在组件内部声明和管理,可以通过setState方法进行更新。
  6. 默认值

    • props:可以为props设置默认值,防止未传递属性时出错。
    • state:可以在组件的构造函数中设置初始状态(state)的默认值。
  7. 更新

    • props:当父组件的props发生变化时,会触发子组件的重新渲染,子组件会收到新的props。
    • state:当组件的状态发生变化时,会触发组件的重新渲染,从而更新界面。

道具更改后如何更新组件

类组件

  1. 父组件传递新的props:父组件可以通过修改传递给子组件的props数据来触发对子组件的更新。这可以通过修改父组件中的 props 值或通过父组件中的状态更改来实现。

  2. componentWillReceiveProps(已弃用和已弃用),getDerivedStateFromProps 或 for
  3. 子组件componentDidUpdate方法:当子组件收到new后props,React 将触发这些生命周期方法之一,具体取决于 React 版本和组件实现。

    • 在 React 16.3 及更早版本中,您可以使用 componentWillReceiveProps 生命周期方法来处理新的 props
    • 在React 16.3及以后版本中,建议使用getDerivedStateFromProps静态方法或componentDidUpdate来处理新的 道具。
  4. 在生命周期方法中更新组件状态或执行其他操作:在上述生命周期方法中,可以访问新的props以及当前的状态组件 (this.propsthis.state) 以及之前的 props 和 状态。组件的状态可以根据新的 props 数据进行更新,从而触发重新渲染。

例如,使用 getDerivedStateFromProps 处理新的 props:

 MyComponent 扩展React .组件 {静态  getDerivedStateFromProps(nextProps, prevState) {   // 检查新道具并根据需要更新状态 if (nextProps.someProp !== prevState .someProp){返回 {someState: nextProps.someProp, };}返回 null; //不更新状态 }渲染()  {//渲染组件返回<div>{这个.状态.某个状态} </div>;}
}

或 componentDidUpdate:

导入反应,{组件}来自'反应' ;类 MyComponent 扩展组件 {状态= {计数: 0,};分量DidUpdate(prevProps, prevState) {if (this.props.someProp !== prevProps.someProp) {console.log('道具更改:', prevProps.someProp, '->', this.props.someProp );}}渲染(){返回 <div>{this.props.someProp}</div>;}
}导出默认MyComponent;

React 16.3及以后的版本,componentWillReceiveProps生命周期方法已经被标记为已废弃,不再推荐使用。正好,推荐使用getDerivedStateFromPropscomponentDidUpdate来处理道具的变化。

函数组件

在函数组件中,可以使用 React 的钩子函数来判断组件更新时,特别是 useEffect 钩子。下面是如何在函数组件中判断组件更新时:

  1. 使用 useEffect 钩子 :使用 useEffect 钩子在函数组件中执行副作用操作,并且可以根据依赖关系确定何时触发这些操作副作用。你可以使用props或者其他状态值作为依赖,当这些依赖发生变化时,useEffect中的代码将会被执行。
导入React,{useEffect}来自'反应'; function MyComponent(props) {// 使用 use用于确定何时更新的效果挂钩 useEffect(() => {//每次组件渲染时都会执行这里的代码  // 这可以根据这里完成新道具操作控制台.log('道具更新:',道具 .一些道具;},[道具.一些道具]);//仅在道具中。 someProp改变时执行 return <div>{props .一些道具}</div>;
}

在上面的示例中,我们有 props.someProp 作为 useEffect 的依赖项,因此当 props.some 时Pro 当 p 发生变化时, useEffect中的代码会被执行,以便可以确定组件何时更新。

  1. 使用React.memo(可选):如果希望功能组件仅在特定props发生变化时更新,并且不关心其他props,可以使用React.memo来包裹函数组件。这将创建一个优化的组件,仅当指定的 props 更改时才会触发重新渲染。
导入反应来自'反应';功能 我的组件(道具) {返回 <div>{prop s.someProp}</div>;
}//使用React.memo包裹组件,只有当someProp改变时才重新渲染
导出 默认反应.备忘录() 我的组件);