在今天的React课程翻译部分中,我们建议您完成下一个实际任务,并向您介绍有关如何修改React组件状态的故事。

→
第1部分:课程概述,React,ReactDOM和JSX普及的原因→
第2部分:功能组件→
第3部分:组件文件,项目结构→
第4部分:父级和子级组件→
第5部分:TODO应用程序的开始工作,样式设计的基础→
第6部分:关于本课程的一些功能,JSX和JavaScript→
第7部分:内联样式→
第8部分:继续研究TODO应用程序,熟悉组件的属性→
第9部分:组件属性→
第10部分:使用组件特性和样式的研讨会→
第11部分:动态标记生成和映射数组方法→
第12部分:研讨会,TODO应用程序的第三阶段工作→
第13部分:基于类的组件→
第14部分:关于基于类的组件,组件状态的研讨会→
第15部分:组件健康研讨会→
第16部分:TODO应用程序的第四阶段工作,事件处理→
第17部分:TODO应用程序的第五阶段工作,修改组件的状态→
第18部分:TODO应用程序的第六阶段工作→
第19部分:组件生命周期方法第20部分:条件渲染的第一课→
第21部分:关于条件渲染的第二课和研讨会→
第22部分:TODO应用程序的第七阶段工作,从外部资源下载数据→
第23部分:关于使用表格的第一课→
第24部分:第二形式课→
第25部分:使用表单的研讨会→
第26部分:应用程序体系结构,容器/组件模式→
第27部分:课程项目课31.讲习班。 TODO应用程序。 阶段数5
→
原创▍工作
启动Todo应用程序时,您可能会注意到控制台中显示了一条通知,指示我们已经在
TodoItem
组件中配置了元素的
checked
属性,但没有提供与该元素进行交互的机制作为
onChange
事件
onChange
。 使用应用程序界面时,这导致无法显示或取消选中页面上显示的标志。
在这里,您被邀请为
TodoItem
组件的
checkbox
类型的元素配备一个
TodoItem
事件处理程序,在当前工作阶段,该事件处理程序足以以将某些内容输出到控制台的函数的形式呈现。
▍解决方案
这是
TodoItem
组件代码现在的样子,存储在
TodoItem.js
文件中:
import React from "react" function TodoItem(props) { return ( <div className="todo-item"> <input type="checkbox" checked={props.item.completed}/> <p>{props.item.text}</p> </div> ) } export default TodoItem
这是启动应用程序时控制台显示的内容。
控制台通知同时,这些标志不响应我们的效果。
为了摆脱此通知并为进一步的工作做好准备,只需将一个
onChange
事件
onChange
分配给
checkbox
元素就足够了。 这是代码中的样子:
import React from "react" function TodoItem(props) { return ( <div className="todo-item"> <input type="checkbox" checked={props.item.completed} onChange={() => console.log("Changed!")} /> <p>{props.item.text}</p> </div> ) } export default TodoItem
在这里,作为处理程序,我们使用一个简单的函数将单词
Checked!
输出到控制台
Checked!
。 同时,单击标志不会导致其状态发生变化,但是来自控制台的通知(如下图所示)消失了。
标记仍无法正常工作,但来自控制台的通知消失了对应用程序进行的微小更改将使我们在处理组件状态的更改之后,可使复选框正确运行。
课程32.更改组件的状态
→
原创让我们从在包含以下代码的
App.js
文件中使用
create-react-app
的标准应用程序开始:
import React from "react" class App extends React.Component { constructor() { super() this.state = { count: 0 } } render() { return ( <div> <h1>{this.state.count}</h1> <button>Change!</button> </div> ) } } export default App
index.js
文件中包含的
index.css
样式
index.css
,包含以下样式描述:
div { display: flex; flex-direction: column; align-items: center; justify-content: center; } h1 { font-size: 3em; } button { border: 1px solid lightgray; background-color: transparent; padding: 10px; border-radius: 4px; } button:hover { cursor: pointer; } button:focus { outline:0; }
在此阶段,该应用程序如下图所示。
浏览器中的应用程序页面今天,我们将讨论如何更改组件的状态。 如果组件具有状态,则可以通过对其进行初始化来在其中存储一些数据。 但是,如果状态无法更改,则组件不会因其存在而特别受益,其中的数据存储与例如在组件代码中硬拷贝它们不会有很大的不同。
让我们讨论一下该应用程序,在该示例中,我们将考虑使用组件的状态。 上面提供了代码的
App
组件是基于类的组件。 这很明显,因为我们需要该组件具有状态。 在组件代码中,我们使用构造函数。
在其中,我们一如既往地调用
super()
方法,并通过将
count
属性写入状态并为其分配初始值
0
来初始化状态。 在
render()
方法中,我们打印一个表示组件状态中
count
属性值的第一级标题,以及带有单词
Change!
的按钮
Change!
。 所有这些都使用样式设置格式。
如果在此应用程序的工作阶段,在浏览器中将其打开并单击按钮,则当然不会发生任何事情。 但是我们需要单击按钮以更改组件的状态,从而影响其
count
属性。 同时,我们已经研究了在React中处理事件的方法,我们的任务是创建一种机制,该机制响应按钮的单击,更改
count
的state属性。
让我们开始解决我们的问题,为按钮配备一个
onClick
事件
onClick
,对于初学者而言,该事件
onClick
将仅向控制台输出一些内容。
为此,我们将向组件类添加一个新方法。 您可以随意调用它,但是习惯上调用此类方法,以便它们的名称可以指示它们正在处理的事件。 结果,由于我们将使用它来处理
click
事件,因此将其称为
handleClick()
。 这是
App
组件代码现在的样子。
import React from "react" class App extends React.Component { constructor() { super() this.state = { count: 0 } } handleClick() { console.log("I'm working!") } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={this.handleClick}>Change!</button> </div> ) } } export default App
请注意,从
render()
引用此方法,我们使用
this.handleClick
形式的
this.handleClick
。
现在,如果您单击按钮,相应的消息将出现在控制台中。
单击按钮将调用类方法。现在,使它成为可能,以便单击该按钮将增加其上方显示的数字,即修改组件的状态。 也许尝试在
handleClick()
方法中直接更改组件的状态? 假设如果我们这样重写此方法:
handleClick() { this.state.count++ }
我必须马上说,这不适用于React中的组件状态。 尝试执行此类代码将引发错误。
组件的状况可以与人穿的衣服进行比较。 如果他想换衣服,他不会在不脱衣服的情况下改变或重新粉刷衣服,而是脱下她并穿上别的东西。 实际上,这正是它们如何处理组件状态。
您可能还记得我们曾经讨论过一种用于修改状态的特殊方法,该方法在基于类的组件中可用,因为它们扩展了
React.Component
类。 这是
setState()
方法。 它用于需要更改组件状态的情况。 该方法可以以不同的方式使用。
回想一下状态是一个对象。 让我们尝试将一个将替换状态的对象传递给
setState()
方法。 我们这样重写
handleClick()
方法:
handleClick() { this.setState({ count: 1 }) }
尝试使用此方法将导致以下错误:
TypeError: Cannot read property 'setState' of undefined
。 实际上,我们现在谈论的内容在React开发人员中引起了很多争议,现在我将向您展示一种解决此问题的非常简单的方法,乍看之下似乎并不寻常。
关键是每次创建一个计划使用
setState()
方法的类方法(在我们的例子中为
handleClick()
setState()
,该方法都必须与
this
相关联。 这是在构造函数中完成的。 修改后的组件代码如下所示:
import React from "react" class App extends React.Component { constructor() { super() this.state = { count: 0 } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState({ count: 1 }) } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={this.handleClick}>Change!</button> </div> ) } } export default App
现在,点击
Change!
按钮
Change!
数字1将出现在其上方,错误消息将不会显示。
按下按钮可修改状态没错,该按钮原来是“一次性的”。 第一次单击后,
0
变为
1
,如果再次单击它,则什么也不会发生。 通常,这不足为奇。 单击按钮时调用的代码会完成其工作,每次将状态更改为新状态,但是在第一次单击按钮后,在
count
属性中存储数字
1
的新状态与旧状态没有区别。 为了解决此问题,请考虑另一种使用
setState()
方法的方法。
如果我们对组件的先前状态不感兴趣,则可以简单地将一个对象传递给此方法,该方法将替换状态。 但是,经常会发生组件的新状态取决于旧状态的情况。 在我们的例子中,这意味着,基于存储在该状态的先前版本中的
count
属性的值,我们希望对该值加1。 如果要更改状态,则需要知道以前存储在状态中的内容,可以将
setState()
方法传递给一个函数,该函数作为参数接收状态的先前版本。 您可以根据需要命名此参数,在本例中为
prevState
。 此功能的采购将如下所示:
handleClick() { this.setState(prevState => { }) }
您可能会认为,在这样的函数中,只需使用表单
this.state
的构造来引用状态就足够了,但是这种方法不适合我们。 因此,此功能接受组件状态的先前版本很重要。
该函数应返回该状态的新版本。 这是
handleClick()
方法
handleClick()
该问题的方式:
handleClick() { this.setState(prevState => { return { count: prevState.count + 1 } }) }
请注意,要获取
count
属性的新值,我们使用
count: prevState.count + 1
构造。 您可能会认为以下形式的
count: prevState.count++
构造
count: prevState.count++
,但是
++
运算符
count: prevState.count++
对其应用
count: prevState.count++
变量,这意味着尝试修改状态的先前版本,因此在此不使用它。
在此阶段,组件文件的完整代码将如下所示:
import React from "react" class App extends React.Component { constructor() { super() this.state = { count: 0 } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState(prevState => { return { count: prevState.count + 1 } }) } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={this.handleClick}>Change!</button> </div> ) } } export default App
现在,每次单击按钮都会增加计数器值。
每次单击按钮都会增加计数器值。我们刚刚发现的内容为我们在开发React应用程序中打开了巨大的机会。
前面我们说过,父组件可以通过属性机制将属性从其自身的状态传递给子组件。 如果React检测到父组件的状态发生了变化,它将重新渲染此状态传递到的子组件。 它看起来像是对
render()
方法的调用。 结果,子组件将反映以父组件状态存储的新数据。
总结
今天,您已经准备好Todo应用程序以进行进一步的工作,并且还熟悉了React中用于更改组件状态的机制。 下次,您将被要求使用今天学到的知识来扩展培训应用程序的功能。
亲爱的读者们! 您如何看待React中组件的状态,而无需使用特殊机制就无法直接更改这一事实?
