资讯专栏INFORMATION COLUMN

React入门系列 - 3 state与props

henry14 / 2200人阅读

摘要:而主要被设计用于维持组件内部私有状态。初始化初始化需要在中进行。对于的定义为请求修改某个数据,而的实现则是将对变量的修改放入一个修改队列中,在一个循环之后进行批量更新结果深入点涉及的更新机制。推出了与版本之后推出来的就是为了解决这些问题的。

3.1 什么是state

我们要认识到,React中的组件其实是一个函数,所以state是函数内部的私有变量,外部其他组件或者方法都是无法直接访问到内部的state。
而state主要被设计用于维持组件内部私有状态。

3.1.1 初始化state

初始化state需要在class中constructor进行。

import React, { PureComponent } from "react"

export default class index extends PureComponent {
  constructor(props){
    super(props)
    this.state = {name:"demo react",time:new Date()}
  }
  render() {
    return (
      
Hello world React!{this.state.name}

组件生成时间:{this.state.time}

) } }

在这个代码中,我们初始化了name,time两个state值。一旦state初始化完成,我们就可以在render中进行访问。

使用npm run dev命令运行,并在浏览器中打开查看吧。

3.1.2 修改state值setState

我们已经知道了如何初始化组件中的state值,那么接下来我们来看看,如何实现修改state的值

  import React, { PureComponent } from "react"

  export default class index extends PureComponent {
    constructor(props){
      super(props)
      this.state = {name:"demo react",time:+new Date()}
    }
    handleUpdateName () {
      this.state.time = (+new Date())
    }
    render() {
      return (
        
Hello world React!{this.state.name}

组件生成时间:{this.state.time}

) } }

有些动作快的同学,第一个想法就是如此修改组件中的state值,但是值得玩味的是,值的确是修改成功了,但是,并没有实时体现在界面上。这究竟是怎么回事呢?

这就要来看看,React中的setState方法。

React对于setState的定义为请求React修改某个数据,而React的实现则是将对变量的修改放入一个修改队列中,在一个循环之后进行批量更新结果(深入点涉及VDom的更新机制)。所以,这里会造成一个问题,就是setState数据之后立刻进行读取,可能你读取到的数据,并非是已经被更新过的有效值。

setState有三种修改数据的方式,让我们来一个一个尝试。

3.1.2.1 直接赋值
  import React, { PureComponent } from "react"

  export default class index extends PureComponent {
    constructor(props){
      super(props)
      this.state = {name:"demo react",time:+new Date()}
    }
    handleUpdateName () {
      // this.state.time = (+new Date())
      console.log("修改前的值",this.state.time)
      this.setState({time:+new Date()})
      console.log("修改后的值",this.state.time)
      let that = this
      setTimeout(function(){
          console.log("当前state值",that.state.time)
      })
    }
    render() {
      return (
        
Hello world React!{this.state.name}

组件生成时间:{this.state.time}

) } }

点击按钮,控制台输出了不同的值,可以观察到setState是采用异步队列模式的。

3.1.2.2 赋值完成等待同步完成之后执行回调

现在出现了一个问题,如果我们需要通过等待setState修改完成的值之后,应该如何处理?React为我们的setState提供了第二个参数callback

  import React, { PureComponent } from "react"

  export default class index extends PureComponent {
    constructor(props){
      super(props)
      this.state = {name:"demo react",time:+new Date()}
    }
    handleUpdateName () {
      // this.state.time = (+new Date())
      console.log("修改前的值",this.state.time)
      this.setState({time:+new Date()},(function(){
          console.log("当前state值",that.state.time)
      })
      console.log("修改后的值",this.state.time)
    }
    render() {
      return (
        
Hello world React!{this.state.name}

组件生成时间:{this.state.time}

) } }

再次运行,并且点击按钮。我们可以看到控制台输出的值是跟第一个方法是一致的。

现在我们来进行一次脑暴,可不可以直接修改state值呢?因为我们在最早直接对state修改的时候,React并未关闭这个对象的set方法。那么我们可否直接通过修改state来进行渲染呢?React中的一个方法为我们解决了这个疑问。

  import React, { PureComponent } from "react"

  export default class index extends PureComponent {
    constructor(props){
      super(props)
      this.state = {name:"demo react",time:+new Date()}
    }
    handleUpdateName () {
        console.log("修改前的值", this.state.time);
        this.state.time = (+new Date())
        console.log("修改后的值", this.state.time);
        console.log("当前state值", this.state.time);
        this.forceUpdate()
    }
    render() {
      return (
        
Hello world React!{this.state.name}

组件生成时间:{this.state.time}

) } }

上面这个代码仅仅用于脑暴,参考,不要在生产环境中使用,因为这个会造成React渲染算法与各种Hook失效,造成全局重新渲染。

3.1.2.3 通过原始数据进行更新

在某些场景下面,我们可能是新的值是基于上一次的值推算而来,所以React提供了setState传递进方法来进行推算处理。

import React, { PureComponent } from "react";

export default class index extends PureComponent {
  constructor(props) {
    super(props);
    this.state = { name: "demo react", time: +new Date() };
  }
  handleUpdateName() {
    console.log("修改前的值", this.state.time);
    let that = this;
    this.setState(oldData => {
      return { time: oldData.time + 1000 };
    });
    console.log("修改后的值", this.state.time);
    setTimeout(function() {
      console.log("当前state值", that.state.time);
    });
  }
  render() {
    return (
      
Hello world React!{this.state.name}

组件生成时间:{this.state.time}

); } }

最后说一点,就是setState是浅拷贝,如果是结构比较深层的对象,很多同学会采用JSON.string()这种来进行深拷贝,这样的操作虽然说是可以的,但是非常影响性能。

React推出了immutable与15版本之后推出来的PureComponent就是为了解决这些问题的。有兴趣的同学可以搜索一下相关资料进行拓展阅读。

3.2 什么是props

我们知道,在函数中有带参数的方法,那么props其实就是传入方法中的参数。并且在React中props是只读属性。在使用场景上,是由父组件向子组件传递值的时候使用的。

3.2.1 接收并渲染props值

我们首先创建一个可以接收props值的组件。

import React, { PureComponent } from "react";

export default class index extends PureComponent {
  constructor(props) {
    super(props);
  }
  
  render() {
    return (
      
{this.props.value||"暂无数据"}
); } }

接着,我们修改Index.js引用这个组件。

import React, { PureComponent } from "react";
import Content from "./content.js"
export default class index extends PureComponent {
  constructor(props) {
    super(props);
    this.state = { name: "demo react", time: +new Date() };
  }
  handleUpdateName() {
    this.setState({time:+new Date()})
  }
  render() {
    return (
      
Hello world React!{this.state.name}

组件生成时间:{this.state.time}

); } }

这里大家有一点要注意,在React中,所有的组件名称第一个字母都必须大写,这是为了与html标签区分出来。

如何向子组件传值呢?就像给html标签增加属性一样。

这样,组件内部可以通过props读取到value值了。不过React的组件传递中有一个很有趣的属性children,这个的用处传递组件包含的内容。

继续修改引入组件的代码,如下

// index.js
主体Children
import React, { PureComponent } from "react";

export default class index extends PureComponent {
  constructor(props) {
    super(props);
  }
  
  render() {
    return (
      
{this.props.value||"暂无数据"},children:{this.props.children}
); } }

最终显示效果就是这样的

原文地址:https://www.yodfz.com/detail/...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100908.html

相关文章

  • React系列React入门

    摘要:原文地址是一个库,主要是通过操作数据的方式去操纵,为什么要重造轮子呢,因为觉的目前市面上的框架对于创建大型应用程序不够直观,不能满足需求,所以诞生了。其实说它性能高,只不过是用的方式计算出最小的操作,所以性能就上来了。 原文地址:https://gmiam.com/post/react-... React 是一个 JS 库,主要是通过操作数据的方式去操纵 DOM,为什么要重造轮子呢,因...

    pf_miles 评论0 收藏0
  • React 可视化开发工具 Shadow Widget 非正经入门(之三:双源属性数据驱动)

    摘要:本篇讲解双源属性不可变数据事件驱动等。可被侦听,被侦听后源头若发生变化,相应的侦听函数将自动被调起。本文完本专栏历史文章介绍一项让可以与抗衡的技术可视化开发工具非正经入门之一三宗罪可视化开发工具非正经入门之二分离界面设计 本系列博文从 Shadow Widget 作者的视角,解释该框架的设计要点。本篇讲解双源属性、不可变数据、事件驱动等。 showImg(https://segment...

    gougoujiang 评论0 收藏0
  • 我的React之路--入门

    摘要:在构造函数里面初始化的数据,把数据放在页面上,点击时候调用方法改变中的数据。是中父组件向子组件通信的方式,下面是一个简单的例子使用组件我是显示的数据我们定义组件时候在构造函数中可以接收到参数,并且要使用传到的构造方法中。 React的学习之路还要继续走下去,最近一边在做未完成的项目一边学习React,项目是vue写的,后面还需要有一个后台管理系统计划使用react完成,寒假说长也不长,...

    qpwoeiru96 评论0 收藏0
  • React入门系列 - 4. 认识无状态组件

    摘要:让他增加一个内部维持的状态另外有一点需要注意,由于是无状态组件,所以,无论是否变更,都会重新刷新这个组件。 4.1 什么是无状态组件 在开发React组件的时候,大家可能会遇到就是我使用的这个组件纯粹就是渲染使用,里面并没有自己的状态、方法、生命周期等等操作。 而为这种组件创建完整的实例有一种浪费机器性能的感觉。 那么,让我们来看看,如何创建一个easy react component...

    cgspine 评论0 收藏0
  • React入门0x008: 生命周期

    0x000 概述 上一章说明了生命周期的概念,本质上就是框架在操作组件的过程中暴露出来的一系列钩子,我们可以选择我们需要的钩子,完成我们自己的业务,以下讲的是react v16.3以下的生命周期,v16.3以及以上的版本有所不同 0x001 组件挂载 以下是组件挂载的过程中触发的声明周期: class App extends React.Component { constructor(pr...

    loonggg 评论0 收藏0

发表评论

0条评论

henry14

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<