React教程第14部分:关于基于类的组件,组件状态的研讨会

在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部分:课程项目

第25课。工作坊。 基于类的组件


原创

▍工作


以下是需要放置在由create-react-app的标准React应用程序的index.js文件中的代码。 将您在此代码中找到的功能组件转换为基于类的组件,此外,查找并修复一个小错误。

index.js文件的代码index.js

 import React from "react" import ReactDOM from "react-dom" // #1 function App() {   return (       <div>           <Header />           <Greeting />       </div>   ) } // #2 function Header(props) {   return (       <header>           <p>Welcome, {props.username}!</p>       </header>   ) } // #3 function Greeting() {   const date = new Date()   const hours = date.getHours()   let timeOfDay     if (hours < 12) {       timeOfDay = "morning"   } else if (hours >= 12 && hours < 17) {       timeOfDay = "afternoon"   } else {       timeOfDay = "night"   }   return (       <h1>Good {timeOfDay} to you, sir or madam!</h1>   ) } ReactDOM.render(<App />, document.getElementById("root")) 

▍解决方案


首先,让我们看看通过在浏览器中打开应用程序以其原始形式给出的内容。


浏览器源页面

您可以看到页面上显示的第一行看起来不正确。 在欢迎之后的逗号后面,显然应该有一个用户名之类的东西。

如果我们分析应用程序代码,结果是Header组件显示此行,期望获得在创建其实例时设置的username属性。 在App组件中创建了此组件的实例。 找到答案后,我们将能够纠正作业中提到的错误。

应该注意的是,组件通常放置在不同的文件中,但是在这种情况下,我们将它们全部描述在一个文件中。

我们继续将App的功能组件转换为基于类的组件。 为此,将其代码转换为以下形式就足够了:

 class App extends React.Component {   render() {       return (           <div>               <Header username="vschool"/>               <Greeting />           </div>       )   } } 

现在, class关键字位于组件名称之前,后跟extends React.Component ,之后,该类的主体在大括号中描述。 应该有一个render()方法返回我们从功能组件返回的内容。 其他组件以相同的方式处理。 注意<Header username="vschool"/>的构造。 在这里,我们将带有vschool值的username属性vschool Header组件,从而解决了原始应用程序中的错误。

如您所知, Header组件希望获得username属性,在功能组件中,可以使用props.username构造访问此属性(在这种情况下, props是描述组件的函数的参数)。 在基于类的组件中,外观类似于this.props.username 。 这是Header组件的重新设计的代码:

 class Header extends React.Component {   render() {       return (           <header>               <p>Welcome, {this.props.username}!</p>           </header>       )   } } 

第三个组件Greeting ,与其他组件略有不同。 事实是,在其中,在return命令之前,需要执行一些计算。 将其转换为基于类的组件时,必须将这些计算结果放在return命令之前的render()方法中。 这是重新设计的Greeting组件的代码:

 class Greeting extends Component {   render() {       const date = new Date()       const hours = date.getHours()       let timeOfDay             if (hours < 12) {           timeOfDay = "morning"       } else if (hours >= 12 && hours < 17) {           timeOfDay = "afternoon"       } else {           timeOfDay = "night"       }       return (           <h1>Good {timeOfDay} to you, sir or madam!</h1>       )   } } 

请注意,此组件已在该组件的声明中使用: class Greeting extends Component 。 为了简洁起见,通常这样做是为了实现此目的,但为了使它起作用,我们需要优化import命令react ,将其转换为以下形式:

 import React, {Component} from "react" 

这是浏览器中回收的应用程序页面的外观。


重新设计了浏览器中的应用程序页面

实际上,它看起来与原始应用程序的页面相同,并且这两个页面之间唯一值得注意的区别是,传递给Header组件的用户名现在显示在第一行中。

这是已处理的index.js文件的完整代码:

 import React, {Component} from "react" import ReactDOM from "react-dom" // #1 class App extends React.Component {   render() {       return (           <div>               <Header username="vschool"/>               <Greeting />           </div>       )   } } // #2 class Header extends React.Component {   render() {       return (           <header>               <p>Welcome, {this.props.username}!</p>           </header>       )   } } // #3 class Greeting extends Component {   render() {       const date = new Date()       const hours = date.getHours()       let timeOfDay             if (hours < 12) {           timeOfDay = "morning"       } else if (hours >= 12 && hours < 17) {           timeOfDay = "afternoon"       } else {           timeOfDay = "night"       }       return (           <h1>Good {timeOfDay} to you, sir or madam!</h1>       )   } } ReactDOM.render(<App />, document.getElementById("root")) 

如果执行此实际任务没有给您带来任何困难-太好了。 如果您仍不太满意基于类的组件,请花一些时间尝试一下。 例如,您可以再次将基于类的组件重新制成功能组件,然后执行逆变换。

课26.组件状态


原创

状态是一个非常重要的React概念。 如果组件需要存储其自己的任何数据并管理该数据(与父组件使用属性机制向其传输数据的情况相反),请使用组件的状态。 今天,我们看一下有关组件状态的基本概念。

状态只是组件控制的数据。 特别是,这意味着组件可以更改此数据。 同时,该组件从父组件获得的我们已经熟悉的属性不能被接收组件更改。 根据React 文档 ,它们是不可变的(immutable)。 例如,如果我们尝试在基于类的组件中使用类似this.props.name = "NoName" ,则会遇到错误消息。

应该注意的是,如果某些组件需要使用状态,那么它应该是基于类的组件。 让我们来谈谈如何通过以下代码片段为组件赋予状态,该代码片段是由create-react-app的标准项目的App.js文件的内容:

 import React from "react" class App extends React.Component {   render() {       return (           <div>               <h1>Is state important to know?</h1>           </div>       )   } } export default App 

这是浏览器中应用程序页面的外观。


浏览器中的应用程序页面

为了使组件具有状态,首先需要创建一个类构造函数。 它看起来像一个constructor()类方法。 之后,组件代码将如下所示:

 class App extends React.Component {   constructor() {         }     render() {       return (           <div>               <h1>Is state important to know?</h1>           </div>       )   } } Constructor() 

这是JavaScript内置的一种特殊方法,旨在基于类创建和初始化对象。 实际上,如果在创建对象时需要初始化某些内容,则相应的操作将完全在constructor()方法中执行。

构造函数代码中要做的第一件事是调用父类的构造函数。 这是使用super()函数完成的。 在父类的构造函数中,可以执行某些初始化操作,其结果对我们的对象很有用。 这是我们的类构造函数现在的样子:

 constructor() {   super() } 

现在,为了使组件具有状态,我们需要在构造函数中将state属性添加到类实例中。 此属性是一个对象:

 constructor() {   super()   this.state = {} } 

这里我们用一个空对象初始化它。 您可以使用this.state构造在组件代码中使用this.state 。 向状态添加一个新属性:

 constructor() {   super()   this.state = {       answer: "Yes"   } } 

现在,让我们考虑一下如何使用代码状态中存储的内容。 回忆一下组件显示的问题Is state important to know? 。 国家存储该问题的答案。 为了在问题后添加此答案,您需要像往常一样通过向JSX代码中添加JavaScript构造来做同样的事情。 即,将{this.state.answer}构造添加到该行的末尾。 结果,完整的组件代码将如下所示:

 class App extends React.Component {   constructor() {       super()       this.state = {           answer: "Yes"       }   }     render() {       return (           <div>               <h1>Is state important to know? {this.state.answer}</h1>           </div>       )   } } 

这是应用程序页面在浏览器中的外观。


浏览器中的应用程序页面

在这里,我想指出的是,组件在初始化期间接收的状态可以在组件的操作期间更改。 此外,组件可以使用处理已知属性的机制将状态传递给后代组件。 例如,在我们的例子中,如果我们假设ChildComponent有某个组件, ChildComponent可以像下面这样将状态的数据传输给它:

 <ChildComponent answer={this.state.answer}/> 

虽然我们不会详细讨论如何更改以组件状态存储的数据。 我们仅注意到,当调用用于解决此问题的setState()方法时,不仅组件的状态将被更改,而且通过属性机制传输到其子组件的状态数据也将被更新。 此外,更改状态将导致来自应用程序页面上显示的状态的数据自动更改。

总结


今天,您有机会使用基于类的组件。 另外,您从此处开始介绍组件状态的概念。 下次,您将找到与国家合作的实际任务。

亲爱的读者们! 如果您在实践中使用React,请告诉我们有关如何管理组件状态的信息。 您是否使用标准的React工具或其他工具?

Source: https://habr.com/ru/post/zh-CN438986/


All Articles