美文网首页
React快速上手4-component、state和props

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

作者: xinyiyake | 来源:发表于2019-02-28 17:19 被阅读0次

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

    1. 组件component

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

    普通组件

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

    • 函数式组件:
    import React from 'react'
    const ListItem = () => {
      return (
        <div>
          <h1>Title</h1>
          <p>Description</p>
        </div>
      )
    }
    
    • 通过class创建组件
    import React, { Component } from 'react'
    
    class ListItem extends Component {
      render() {
        return (
          <div>
            <h1>Title</h1>
            <p>Description</p>
          </div>
        )
      }
    }
    

    在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 (
          <div>
            <h1>Title</h1>
            <p>Description</p>
          </div>
        )
      }
    }
    

    获取state

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

    class ListItem extends Component {
      constructor(props) {
        super(props)
        this.state = {
          hasClicked: false
        }
      }
      render() {
        return (
          <div>
            <h1>Title</h1>
            <p>Description</p>
            <p>Clicked: {this.state.hasClicked}</p>
          </div>
        )
      }
    }
    

    改变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 (
        <div>count: {count}</div>
      )
    }
    const ChildB = ({add}) => {
      return (
        <div onClick={this.add}>加1</div>
      )
    }
    class FatherComp extend Component {
      constructor(props){
        super(props){
          this.state = {
            count:0
          }
        }
      }
      add = () => {
        this.setState({
          count: this.state.count+1
        })
      }
      render(){
        return (
          <div>
            <ChildA count={this.state.count} />
            <ChildB add={this.add} />
          </div>
        )
      }
    }
    

    3. props

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

    const ListItem = props => {
      return (
        <div>
          <h1>{props.title}</h1>
          <p>{props.description}</p>
        </div>
      )
    }
    

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

    import React, { Component } from 'react'
    
    class ListItem extends Component {
      render() {
        return (
          <div>
            <h1>{this.props.title}</h1>
            <p>{this.props.description}</p>
          </div>
        )
      }
    }
    

    传递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'
    //...
    <ListItem title="A blog post" description={desc} />
    

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

    children

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

    <ListItem title="A blog post" description="{desc}">
      Something
    </ListItem>
    

    例子中,在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 (
          <div>
            <h1>{this.props.title}</h1>
            <p>{this.props.description}</p>
          </div>
        )
      }
    }
    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

          本文链接:https://www.haomeiwen.com/subject/awhhyqtx.html