vlambda博客
学习文章列表

【前端开发日常 - 13】React学习笔记(3)——Props & State & Fragments

Props

Props 用作组件的输入,是一个值或多个值的对象,使用时类似于 HTML 标 属性的方式传递给组件。它们是从父组件传递到子组件的数据。

Props 的主要目的是提供以下组件功能:

  1. 将自定义数据传递到组件。

  2. 触发状态更改。

  3. 在组件的 render() 方法中通过 this.props 使用。

在前面的例子中,我们就是定义了一个 message 属性,并且在父级组件调用时传递了 message 的值:

<GreetingComponent message="World"/> 

然后在 GreetingComponent 组件中我们使用 this.props.message 得到了父级传过来的值。

Fragments

前面提到过我们的JSX会被babel编译成 React.createElement() 的形式,而 React.createElement() 第一个参数就需要接收一个元素类型,如果我们并排写了多个元素,babel并不知道我们需要返回的元素类型是什么,代码会异常,紧接着上面代码,假设需要添加一个按钮到 GreetingComponent 组件,下面的方式是 不正确的 :

// src/components/GreetingComponent.jsx
import React, { Component } from 'react';

export default class GreetingComponent extends React.Component {
    render() {
      return <h1>{`Hello, ${this.props.message}`}</h1><button>button</button>
    }
}

我们将会得到如下的报错:

./src/components/GreetingComponent.jsx
  Line 5:  Parsing error: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?

处理方法1:将需要返回的元素包裹到一个新的元素里面:

// src/components/GreetingComponent.jsx
import React, { Component } from 'react';

export default class GreetingComponent extends React.Component {
    render() {
      return <div>
        <h1>{`Hello, ${this.props.message}`}</h1>
        <button>button</button>
      </div>

    }
}

通过浏览器审查元素,我们可以看到,有一个 div 包裹了 h1 和 button ,但是我们不需要这个多余的 div ,在使用了react 版本 16之后就有了处理方法二:

// src/components/GreetingComponent.jsx
import React, { Component } from 'react';

export default class GreetingComponent extends React.Component {
    render() {
      return <React.Fragment>
        <h1>{`Hello, ${this.props.message}`}</h1>
        <button>button</button>
      </React.Fragment>

    }
}

将 div 换成了 React.Fragment,当然,我们可以像错误提示里面一样使用 <></> 来包裹。

State

State是组件的状态,它是包含一些属性的一个对象,这些属性的值能在组件的生命周期更改。而每次更改state里面的值,我们的组件都会重新执行render,返回新的JSX,因此要使得状态尽量简单,减少修改和状态组件的使用。以前面的使用为例,增加state:

import React, { Component } from 'react';

export default class GreetingComponent extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      buttonText'按钮文字'
    }
  }

  render() {
    const { buttonText } = this.state;
    return <React.Fragment>
      <h1>{`Hello, ${this.props.message}`}</h1>
      <button>{buttonText}</button>
    </React.Fragment>

  }
}

State(状态)是私有的,在组件外无法访问。

State和props的异同

相同点

  1. State和props都是普通的 JavaScript 对象

  2. State和props都能影响渲染

  3. State和props都能从父组件接收初始值

  4. State和props都能在子组件设置默认值

  5. State和props都能作为子组件的初始值

不同点

  1. State用于组件内部对自己进行进行管理,props用于传递值到组件

  2. State不能在父组件改变值,props能在父组件改变值

  3. State能在组件内部改变,props不能在组件内部改变

更新state

直接更新state状态是不能重新渲染的,需要调用 setState() 方法。当状态更改时,组件将会重新渲染。

// 错误
this.state.message = 'Hello world'

// 正确
this.setState({ message: 'Hello World' })

setState() 是异步的,当 setState 调用之后,组件开始渲染,然后回调函数将会被调用。单不建议使用回调函数处理后续逻辑,应该使用组件的生命周期方法。

this.setState({ message: 'Hello World' }, () => {console.log('message更新并渲染')})