jtwang7 / React-Note

React 学习笔记
8 stars 2 forks source link

React - props vs state #1

Open jtwang7 opened 3 years ago

jtwang7 commented 3 years ago

React - props vs state

参考文章: ReactJS: Props vs. State

Props

props 在某种意义上,你可以将它理解为 React 组件所接受的参数,类似于函数形参。

官方文档原话:props 是传递给组件的(类似于函数的形参)。 ReactJS: Props vs. State原话:the property is passed to the component, similar to how an argument is passed to a function.

分析

React 组件有两种写法:

props 在 class 组件下的写法:

class Child extends React.Component {
  constructor( props ) {
    super( props );
  }
  return (
    <div>...</div>
  )
}

props 在函数组件下的写法:

function Child ( props ) {
  return (
    <div>...</div>
  )
}

比较这两种写法中的 props,可以发现,其充当的都是函数(或构造函数)形参的角色。

转化下思路去理解 React 组件和 props。

  • React 组件可以看作是一个函数,定义 React 组件其实就是定义一个函数,唯一特殊点在于该函数返回了一个 React 元素。
  • props 可以看作传递给 React 组件的形参,效果等同于向一个普通函数传递参数。
  • React 组件通过 <Child /> 的 JSX 元素形式调用,props 则作为 JSX 元素属性形式传递。

defaultProps

我们用形参的概念来理解 props,可知 props 一般是从外界传入的,在ReactJS: Props vs. State原话中说的是”props ’come from above.‘“。此外,我们知道函数形参(ES6)中是可以赋予默认值的,props 也可以赋予默认值,虽然不常用,但一个 React 组件可以在创建时赋予默认值。

Welcome.defaultProps = { name: "world", };

* 函数式组件 props 默认值创建(通过对象解构):
```js
function Welcome (props) {
  const {
    name = "world",
  } = props;

  render() {
    return <h1>Hello {this.props.name}</h1>;
  }
}

★ props should not change !!!

props 在 React 组件中需要重点关注的特点 —— 不可变性 (immutable)。我们不能够在一个生命周期内对传入 React 组件的 props 做任何的改动,包括对其赋值或替换原有值等,但我们可以利用 props 计算并返回新的值。即 props 可被看作是一个只读属性。

  • 有人会问:普通函数的形参(args)可以修改,React 组件的 props 不能修改,那为什么你之前还说它们两个是相似的呢?
  • 答:props 与 args 在某种角度上理解,确实是极其相似的,即使是当前提及 props 不可变性时也不例外,因为在 React 中,仅使用 props 的组件(不使用 state)实际上可以看作是一个纯函数”pure function“,纯函数就体现在于,它只读取形参而不对其做任何的修改,结果就是当传入形参不变时,最终输出结果都始终相同。仅使用 props 的 React 组件也是一样,它接收上级传下来的 props,确保不对其做任何的修改,那么若 props 相同,最终 React 组件的渲染结果都是一样的。 ReactJS: Props vs. State原话:Since props are passed in, and they cannot change, you can think of any React component that only uses props (and not state) as “pure,” that is, it will always render the same output given the same input. This makes them really easy to test - win!

State

state 在某种意义上,你可以将它理解为 React 组件内部定义的变量,由该组件私有管理,只能作用于组件内部。官方文档中,将 state 类比为一个在函数内声明的变量。个人认为这样类比仍有点欠妥,在学习和实践的基础上,我认为:

由于 state 是用来操作 React 组件渲染结果的,因此当组件需要跟踪渲染之间的信息时,就需要创建,更新并使用 state。

ReactJS: Props vs. State原话:When a component needs to keep track of information between renderings the component itself can create, update, and use state.

State vs Props

  1. state is created in the component state 是在 React 组件内创建的,只能应用于该组件(类似于”在函数内创建的变量,受限于该函数的作用域“)。state 可以直接赋值,也可以接收 props 作为其初始化值(与普通函数内变量使用相同,普通函数内变量也可以通过形参初始化)。 props 是由外部传入的,也可以在组件内赋予默认值。

    state 可接收 props 作为初始化值(或用 props 计算初始化值),这为操作 props 提供了方法。props 是不能被修改的,我们可以将其拷贝为另一个值,再对拷贝值进行修改(注意引用类型的问题)。

  2. state is changeable state 是可修改的。而 props 是不能修改的。 state 必须通过 setState() 更新,setState() 为 state 提供了监听功能,只有通过 setState() 才能监听到 state 的变化并触发重新渲染,不能直接修改 state 值,这样是无法触发组件重渲染的。

    在 Vue 中组件重新渲染是通过数据双向绑定的方式触发的,其通过每个数据上的监听对象来判断是否需要重新渲染,并自动决定渲染时机。而在 React 中,数据监听是单向的,在 state 中定义的变量会被”添加“到监听列表内,其数据变化会被 diff 算法比较并捕获。与 Vue 不同在于,React 需要通过手动调用 setState 来触发 state 更新以及组件重渲染。

  3. state 与 props 在不同组件间的联系:state 可以接收 props,同样 state 也可以作为 props 传递给下一个子组件。
jtwang7 commented 3 years ago

2021-05-19 关于 State 的新理解

在之前阅读的文章中,许多地方在讲述 state 时都提到了 state 用于跟踪组件渲染信息的这一特点。当时没有特别注意,在项目实际开发时有所感悟,记录如下。

ReactJS: Props vs. State原话:When a component needs to keep track of information between renderings the component itself can create, update, and use state. 翻译过来意思就是:state 是用来操作 React 组件渲染结果的,因此当组件需要跟踪渲染之间的信息时,就需要创建,更新并使用 state。 我反复提及这句话的原因就在于,它很全面地概括了我们为何要使用 state,何时使用 state。


为了更好地理解 state 在 React 组件中的用途,我们需要了解一些 React 组件的渲染机制。


学习心得:如果在 React 组件中,我们期望组件”状态“能在每次更新时触发重新渲染,并且重新渲染后值能够被组件追踪并保留, 那么 state 就是我们的选择之一。React 中很多设计本质上都涉及了对组件状态或行为的跟踪,同时选择性地执行一些额外操作。


有人会问:如果一个函数内部变量在重复调用时被重复声明,那么我们将其作为参数传入不就可以了? 答:理论上,利用函数的闭包特性是可行的,但是我们知道 React 组件实际最终会渲染成一个 DOM 树结构,我们无法判断重新渲染时,会渲染哪一部分(因为我们要保证变量只存在于不被渲染的部分)。因此,最稳妥的方法就是将所有状态定义到顶层,很显然这是不可取的。