资讯专栏INFORMATION COLUMN

【全栈React】第6天: 状态

leo108 / 1620人阅读

摘要:无论何时状态改变通过,组件将重新投递。在调用函数之后,我们可以将第二个参数传递给函数,该函数将在状态更新后保证被调用。今天,我们更新了我们的组件以使其处于状态状态,现在有必要处理如何使组件成为状态。

本文转载自:众成翻译
译者:iOSDevLog
链接:http://www.zcfy.cc/article/3824
原文:https://www.fullstackreact.com/30-days-of-react/day-6/

今天我们开始了解React中有状态组件的工作原理,并且看看我们何时以及为什么要使用状态。

我们几乎完成了在React开始运行的第一周。我们通过JSX工作,构建我们的第一个组件,设置父子关系,并使用React驱动组件属性。我们还有一个重要的想法,我们还没有讨论React _状态_相关的知识。

有关状态的事

React并没有让我们修改this.props 我们有充分的理由的组件。想象一下,如果我们将 title 属性支持传递给Header 组件,并且Header 组件能够修改它。我们如何知道titleHeader 组件的什么 ?我们设置了竞争条件,混乱的数据状态,并且将是一个全面的坏主意,修改由父组件传递给我们的变量并在小孩中修改。

然而,有时组件需要能够更新自己的状态。例如,active 在秒表上设置标志或更新计时器。

虽然最好props 尽可能多地使用,但有时我们需要坚持组件的状态。为了处理这个问题,React使我们有能力在组件中拥有_状态_。

组件里的state 意图完全是内部的组件,它的孩子(即组件和任何孩子使用它访问)。类似于我们如何props 在组件中访问,可以通过this.state 组件访问状态。无论何时状态改变(通过 this.setState() ),组件将重新投递。

例如,假设我们有一个简单的时钟组件来显示当前时间:

即使这是一个简单的时钟组件,它确实保留状态,因为它需要知道当前显示的时间。没有使用state,我们可以设置一个计时器并重新渲染整个React组件,但页面上的其他组件可能不需要重新渲染…这将是一个头痛的问题。

相反,我们可以设置一个计时器来调用组件内部的rerender并更改此组件的内部状态。

我们来建立这个组件。首先,我们将创建我们将要调用的组件Clock。在进入状态之前,我们来构建组件并创建该render() 函数。我们需要考虑数字,如果数字小于10,在数字前面加上一个零(0),并进行相应的设置 am/pmrender()函数的最终结果可能如下所示:

class Clock extends React.Component {
  render() {
    const currentTime = new Date(),
          hours = currentTime.getHours(),
          minutes = currentTime.getMinutes(),
          seconds = currentTime.getSeconds(),
          ampm = hours >= 12 ? "pm" : "am";

    return (
      
{ hours == 0 ? 12 : (hours > 12) ? hours - 12 : hours }:{ minutes > 9 ? minutes : `0${minutes}` }:{ seconds > 9 ? seconds : `0${seconds}` } {ampm}
) } } // ... export default Clock

如果我们渲染我们的新Clock 组件,我们只会在组件本身重新运行时获得时间。这不是一个非常有用的时钟(还)。为了将静态时间显示Clock 组件转换为显示时间的时钟,我们需要每秒更新一次。

为了做到这一点,我们需要跟踪组件状态下的_current_ 时间。 为此,我们需要设置初始状态值。 在ES6类样式中,我们可以通过将this.state 设置为一个值来设置constructor() 中组件的初始状态。

constructor(props) {
    super(props);
    this.state = this.getTime();
}

构造函数的第一行应该_始终_调用 super(props)。如果您忘记了这一点,组件将不会非常喜欢(即会有错误)。

现在我们this.stateClock 组件中有一个定义,我们可以在 render() 函数中引用它this.state。让我们更新我们的 render() 函数this.state来获取以下值:

class Clock extends React.Component {
  // ...
  render() {
    const {hours, minutes, seconds, ampm} = this.state;
    return (
      
{ hours === 0 ? 12 : (hours > 12) ? hours - 12 : hours }:{ minutes > 9 ? minutes : `0${minutes}` }:{ seconds > 9 ? seconds : `0${seconds}` } {ampm}
) } }

我们现在可以更新 state 组件而不是直接使用数据值。为了更新状态,我们将使用该函数 this.setState(),这将触发组件重新渲染。

在我们的Clock 组件中,我们使用本机setTimeout() JavaScript函数创建一个定时器,以this.state 在1000毫秒内更新对象。我们将把这个功能放在一个函数中,我们再次调用它。

class Clock extends React.Component {
  // ...
  constructor(props) {
    super(props);
    this.state = this.getTime();
  }
  // ...
  setTimer() {
    clearTimeout(this.timeout);
    this.timeout = setTimeout(this.updateClock.bind(this), 1000);
  }
  // ...
  updateClock() {
    this.setState(this.getTime, this.setTimer);
  }
  // ...
}

我们将在下一节中介绍生命周期中的钩子,但是为了简单起见,我们暂时将其简称为constructor()

在该 updateClock() 函数中,我们将要在新时间内更新状态。我们现在可以在 updateClock() 函数中更新状态:

class Clock extends React.Component {
  // ...
  updateClock() {
    this.setState(this.getTime, this.setTimer);
  }
  // ...
}

该组件将安装在页面上,并在(大约)一秒钟(1000毫秒)内更新当前时间。但是,它不会再重新设置。我们可以在setTimer()函数结束时再次调用该函数:

class Clock extends React.Component {
  // ...
  updateClock() {
    const currentTime = new Date();
    this.setState({
      currentTime: currentTime
    })
    this.setTimer();
  }
  // ...
}

现在,组件本身可能会比超时功能再次调用慢,这将导致重新出现的瓶颈,并且不必要地在移动设备上使用宝贵的电池。在调用setTimer() 函数之后this.setState(),我们可以将第二个参数传递给this.setState()函数,该函数将在状态更新_后_保证被调用。

class Clock extends React.Component {
  // ...
  updateClock() {
    const currentTime = new Date();
    this.setState({
      currentTime: currentTime
    }, this.setTimer);
  }
  // ...
}
更新我们的活动列表

我们可以Header 在上一节中我们一直在研究的活动列表中更新我们的组件。当用户点击search 图标,我们将要显示组件。

尝试一下!点击下面的搜索图标:(想要有效果还是去原文体验吧?)

知道我们现在知道的是,现在 this.state 我们可以更新视图来添加条件呈现

class Header extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      searchVisible: false
    }
  }

  // toggle visibility when run on the state
  showSearch() {
    this.setState({
      searchVisible: !this.state.searchVisible
    })
  }

  render() {
    // Classes to add to the  element
    let searchInputClasses = ["searchInput"];

    // Update the class array if the state is visible
    if (this.state.searchVisible) {
      searchInputClasses.push("active");
    }

    return (
      
{this.props.title} {/* Adding an onClick handler to call the showSearch button */}
) } }
有些事情要记住

当我们调用this.setState() 一个对象参数时,它将执行一个数据的_浅合并_到可用的对象中this.setState() ,然后重新渲染组件。

我们通常只想在我们的状态中保持我们将在该render() 函数中使用的值。从上面我们的时钟的例子,请注意,我们的存储hours,minutes,以及seconds 在我们的状态。在我们不打算在render功能中使用的状态下存储对象或计算通常是一个坏主意,因为它可能导致不必要的渲染和浪费的CPU周期。

正如我们在本节顶部指出的那样,props不仅出于性能原因,最好使用,但是因为有状态的组件更难测试。

今天,我们更新了我们的组件以使其处于状态状态,现在有必要处理如何使组件成为状态。明天我们将进入组件的生命周期,何时/如何与页面进行交互。

MenuButton

上面提到的组件在代码库中,只是为菜单按钮提供了一个很好的显示。

const MenuButton = (props) => (
  
)

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

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

相关文章

  • 全栈ReactReact 30教程索引

    摘要:今天我们将讨论创建组件的最终方案,即无状态函数的纯组件。今天我们正在研究一种处理提出的复杂数据的方法,称为体系结构。第天部署介绍今天,我们将探讨部署我们的应用所涉及的不同部分,以便外界可以使用我们的应用。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3758原文:https://www.fullstackreact.com/3...

    appetizerio 评论0 收藏0
  • 全栈React30: 总结和更多的资源

    摘要:本文转载自众成翻译译者链接原文我们做到了第天。欢迎来到最后一天恭喜你做到了我们此行的最后一个部分是通过参与。反应社区是活跃成长和友好的。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3800原文:https://www.fullstackreact.com/30-days-of-react/day-30/ 我们做到了!第30天...

    Miracle_lihb 评论0 收藏0
  • 全栈React11: 纯组件

    摘要:今天我们将讨论创建组件的最终方案,即无状态函数的纯组件。为了获得更多的性能和简单性,同样允许我们使用正常的函数创建纯粹的,无状态的组件。在中,功能组件被称为一个参数的类似于构造函数类,它们是它所调用的,以及组件树的当前。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3819原文:https://www.fullstackrea...

    Cciradih 评论0 收藏0
  • 全栈React24: 测试应用

    摘要:我们的第一个假设是非常简单的测试。我们正在测试以确保元素被包装在类中。在我们编写的每个测试中我们都需要将应用呈现在工作测试文档中。作为提醒我们可以使用命令或命令来运行测试。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3804原文:https://www.fullstackreact.com/30-days-of-react/...

    ziwenxie 评论0 收藏0
  • 全栈React1: 什么是 React?

    摘要:本文转载自众成翻译译者链接原文今天,我们从一开始就开始。让我们看看是什么,是什么让运转起来。什么是是一个用于构建用户界面的库。它是应用程序的视图层。所有应用程序的核心是组件。组件是可组合的。虚拟完全存在于内存中,并且是网络浏览器的的表示。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3765原文:https://www.ful...

    ralap 评论0 收藏0

发表评论

0条评论

leo108

|高级讲师

TA的文章

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