React快速上手4-component、state和props

前言:之前的文章中我们快速撸过一遍ES6语法和jsx语法,这些都是为了开发react组件所做的准备,在本节中,将真正进入react开发实践当中。

1. 组件component

根据react官网对组件的描述是这样:组件就像JavaScript函数,它们接受任意输入(称为“props”)并返回描述屏幕上应显示内容的React元素。在react中,我们可以认为,一切都是一个组件,即使是纯HTML标签也是它们自己的组件。

普通组件

在react中,我们有两种方式来创建组件:

  • 函数式组件:
import React from 'react'
const ListItem = () => {
  return (
    

Title

Description

) }
  • 通过class创建组件
import React, { Component } from 'react'

class ListItem extends Component {
  render() {
    return (
      

Title

Description

) } }

在React Hooks出现之前,只有通过class来创建的组件才有自己的状态,可以访问react中的生命周期方法,比如componentDidMount(),shouldComponentUpdate()等等,以便在首次呈现,更新或删除组件时执行操作。而通过函数生命的组件又称为无状态组件,没有组件的生命周期方法。React Hooks的出现改变了这一点,我们的功能组件现在比以往任何时候都强大得多,但是目前class仍然是创建组件的完美有效方式。

2. 状态(state)

在react中,我们可以通过设置,改写state来进行与组件状态的交互。

设置默认的state

在Component的构造函数中,初始化this.state。例如,ListItem组件:

class ListItem extends Component {
  constructor(props) {
    super(props)
    this.state = {
      hasClicked: false
    }
  }
  render() {
    return (
      

Title

Description

) } }

获取state

我们可以通过this.state.hasClicked来获取hasClicked的值

class ListItem extends Component {
  constructor(props) {
    super(props)
    this.state = {
      hasClicked: false
    }
  }
  render() {
    return (
      

Title

Description

Clicked: {this.state.hasClicked}

) } }

改变state

react中,我们不能通过直接修改的方式来赋值:

// 无效的方式
this.state.hasClicked = false

而是通过给setState()方法传递一个对象的方式来实现对state的修改:

// 有效的方式
this.setState({ hasClicked: false })

这个传递的对象可以是state的一个子集,也可是一个state的超集,只有你传递的属性才会被修改,省略的属性将保持不变。当我们调用setState方法后,react就会知道state已经改变了,然后会调用一系列的方法,导致组件的刷新和DOM更新。

单向数据流

state始终只由一个组件拥有,更改一个state的值,只会影响这个组件或是这个组件的子组件,这也是为什么state会经常在组件树中向上移的原因。举个例子,如果两个组件需要共享状态,我们就需要把这个共享状态移动到它们共同的祖先组件里,通过props来传递值,我们可以通过在祖先组件中定义一个方法,再通过props传递到子组件中来调用,以达到两个组件都能共享和修改这个共享的state的目的。

const ChildA = ({count}) => {
  return (
    
count: {count}
) } const ChildB = ({add}) => { return (
加1
) } class FatherComp extend Component { constructor(props){ super(props){ this.state = { count:0 } } } add = () => { this.setState({ count: this.state.count+1 }) } render(){ return (
) } }

3. props

在react中,我们通过props进行父子组件间的传值,每个子组件都从父组件获取其props。
在一个函数组件中,props就是它传递的全部内容,并且可以通过添加props作为函数参数来获取它们:

const ListItem = props => {
  return (
    

{props.title}

{props.description}

) }

在类组件中,props默认就被传递,因此,我们没有必要去额外做些什么,我们可以通过this.props来获取:

import React, { Component } from 'react'

class ListItem extends Component {
  render() {
    return (
      

{this.props.title}

{this.props.description}

) } }

传递props是父组件向子组件传值的最好方法,子组件可以通过其props保存数据(有state)或接收数据。
但是props也有其局限性:

  • props有可能通过好几级的组件传递进来,不方便使用
  • 你有可能需要去访问一个完全不相关的组件的state,这种情况用props很难实现

props默认值

在初始化时候,如果我们没有任何值能够获取到,我们需要定义一个默认值,否则这个props值就会丢失掉:

ListItem.propTypes = {
  title: PropTypes.string,
  description: PropTypes.string
}

ListItem.defaultProps = {
  title: '',
  description: ''
}

props的传递

初始化组件时,以类似于HTML属性的方式传递props:

const desc = 'A description'
//...

这个例子中,我们将title作为string传递,并将description作为desc这个变量来传递。

children

children是一个特殊的props,它包含了组件body中传递的任何值:


  Something

例子中,在ListItem组件里,我们可以通过this.props.children来获取到“Something”。

propTypes

由于JavaScript是一种动态类型语言,我们没有办法在编译时强制定义变量的类型,因此如果我们传递一个无效类型,在运行时可能会报错或者产生不是我们期望的结果。
避免这种方式的一种方法是使用TypeScript,但React有一种直接对props类型有帮助的方法,可以在运行代码时帮助我们检测出传递错误的值:

import PropTypes from 'prop-types'
import React from 'react'
class ListItem extends Component {
  render() {
    return (
      

{this.props.title}

{this.props.description}

) } } ListItem.propTypes = { title: PropTypes.string, description: PropTypes.string } export default ListItem

下面是一些我们能够设置的基本类型:

  • PropTypes.array
  • PropTypes.bool
  • PropTypes.func
  • PropTypes.number
  • PropTypes.object
  • PropTypes.string
  • PropTypes.symbol

持续更新中

上一篇:React快速上手3-JSX快速入门
下一篇:React快速上手5-react中的事件和生命周期函数

你可能感兴趣的:(React快速上手4-component、state和props)