diff --git a/03-front-end-libraries/react.json b/03-front-end-libraries/react.json
index 51205cd..f4168f1 100644
--- a/03-front-end-libraries/react.json
+++ b/03-front-end-libraries/react.json
@@ -18,13 +18,13 @@
"title": "Create a Simple JSX Element",
"releasedOn": "December 25, 2017",
"description": [
- "Intro: React is an Open Source view library created and maintained by Facebook. It's a great tool to render the User Interface (UI) of modern web applications.",
- "React uses a syntax extension of JavaScript called JSX that allows you to write HTML directly within JavaScript. This has several benefits. It lets you use the full programmatic power of JavaScript within HTML, and helps to keep your code readable. For the most part, JSX is similar to the HTML that you have already learned, however there are a few key differences that will be covered throughout these challenges.",
- "For instance, because JSX is a syntactic extension of JavaScript, you can actually write JavaScript directly within JSX. To do this, you simply include the code you want to be treated as JavaScript within curly braces: { 'this is treated as JavaScript code' }
. Keep this in mind, since it's used in several future challenges.",
- "However, because JSX is not valid JavaScript, JSX code must be compiled into JavaScript. The transpiler Babel is a popular tool for this process. For your convenience, it's already added behind the scenes for these challenges. If you happen to write syntactically invalid JSX, you will see the first test in these challenges fail.",
- "It's worth noting that under the hood the challenges are calling ReactDOM.render(JSX, document.getElementById('root'))
. This function call is what places your JSX into React's own lightweight representation of the DOM. React then uses snapshots of its own DOM to optimize updating only specific parts of the actual DOM.",
+ "简介:React是由 Facebook 创建和维护的开源视图库。它是渲染当代 Web 应用程序用户界面(UI)的绝佳工具。",
+ "React 使用名为 JSX 的 JavaScript 语法扩展,允许您直接在 JavaScript 中编写 HTML。这有几个好处。它允许您在 HTML 中使用 JavaScript 的完整程序功能,并有助于保持代码的可读性。在大多数情况下,JSX 类似于您已经学过的 HTML,但是在这些挑战中将会涉及一些关键差异。",
+ "例如,因为 JSX 是 JavaScript 的语法扩展,所以您实际上可以直接在 JSX 中编写 JavaScript。要做到这一点,您只需在花括号中包含您希望被视为 JavaScript 的代码:{“这被视为 JavaScript 代码”}
。记住这一点,因为它将用于接下来的几个挑战。",
+ "但是,由于 JSX 不是有效的 JavaScript,因此必须将 JSX 代码编译为 JavaScript。在这个过程中,转换器 Babel 是一个很受欢迎的工具。为了您的方便,它已经添加在了这些挑战的后台。如果您碰巧编写的 JSX 语法无效,您将看到这些挑战中的第一个测试失败。",
+ "值得注意的是,这些挑战在底层调用ReactDOM.render(JSX, document.getElementById('root'))
。这个函数调用是将你的 JSX 置于 React 自己的轻量级 DOM 中。然后,React 使用自己的 DOM 快照来优化更新实际 DOM 的特定部分。",
"
div
element to the constant JSX
. Replace the div
with an h1
element and add the text Hello JSX!
inside it."
+ "说明:当前代码使用 JSX 将div
元素分配给常量JSX
。将div
替换为h1
元素,并在其中添加文本Hello JSX!
。"
],
"files": {
"indexjsx": {
@@ -44,12 +44,12 @@
},
"tests": [
{
- "text": "The constant JSX
should return an h1
element.",
- "testString": "assert(JSX.type === 'h1', 'The constant JSX
should return an h1
element.');"
+ "text": "常量JSX
应该返回一个h1
元素。",
+ "testString": "assert(JSX.type === 'h1', '常量JSX
应该返回一个h1
元素。');"
},
{
- "text": "The h1
tag should include the text Hello JSX!
",
- "testString": "assert(Enzyme.shallow(JSX).contains('Hello JSX!'), 'The h1
tag should include the text Hello JSX!
');"
+ "text": "h1
标签应该包含文本Hello JSX!
。",
+ "testString": "assert(Enzyme.shallow(JSX).contains('Hello JSX!'), 'h1
标签应该包含文本Hello JSX!
。');"
}
],
"solutions": [
@@ -64,19 +64,19 @@
"title": "Create a Complex JSX Element",
"releasedOn": "December 25, 2017",
"description": [
- "The last challenge was a simple example of JSX, but JSX can represent more complex HTML as well.",
- "One important thing to know about nested JSX is that it must return a single element.",
- "This one parent element would wrap all of the other levels of nested elements.",
- "For instance, several JSX elements written as siblings with no parent wrapper element will not transpile.",
- "Here's an example:",
- "Valid JSX:",
+ "上一个挑战是 JSX 的一个简单示例,但 JSX 也可以表示更复杂的 HTML。",
+ "关于嵌套的 JSX,你需要知道的一件重要的事情,那就是是它必须返回单个元素。",
+ "这个父元素将包裹所有其他级别的嵌套元素。",
+ "例如,几个作为兄弟元素而编写的JSX元素没有父元素包裹将不会被转换。",
+ "这里是一个示例:",
+ "有效的 JSX:",
"<div>", - "Invalid JSX:", + "无效的 JSX:", "
<p>Paragraph One</p>
<p>Paragraph Two</p>
<p>Paragraph Three</p>
</div>
<p>Paragraph One</p>", "
<p>Paragraph Two</p>
<p>Paragraph Three</p>
JSX
that renders a div
which contains the following elements in order:",
- "An h1
, a p
, and an unordered list that contains three li
items. You can include any text you want within each element.",
- "Note: When rendering multiple elements like this, you can wrap them all in parentheses, but it's not strictly required. Also notice this challenge uses a div
tag to wrap all the child elements within a single parent element. If you remove the div
, the JSX will no longer transpile. Keep this in mind, since it will also apply when you return JSX elements in React components."
+ "定义一个新的常量JSX
,渲染一个div
,其中依次包含以下元素:",
+ "一个h1
,一个p
,一个包含三个li
项的无序列表。您可以在每个元素中包含任何您想要的文本。",
+ "注意: 当像这样渲染多个元素时,你可以把它们都用圆括号括起来,但是这并不是必须的。还请注意,此挑战使用div
标签把所有子元素包裹在单个父元素中。如果删除div
,JSX将不再转换。请记住这一点,因为当您在React组件中返回JSX元素时它也适用。"
],
"files": {
"indexjsx": {
@@ -95,24 +95,24 @@
},
"tests": [
{
- "text": "The constant JSX
should return a div
element.",
- "testString": "assert(JSX.type === 'div', 'The constant JSX
should return a div
element.');"
+ "text": "常量JSX
应该返回一个div
元素。",
+ "testString": "assert(JSX.type === 'div', '常量JSX
应该返回一个div
元素。');"
},
{
- "text": "The div
should contain a p
tag as the second element.",
- "testString": "assert(JSX.props.children[1].type === 'p', 'The div
should contain a p
tag as the second element.');"
+ "text": "div
应该包含一个p
标签作为第二个元素。",
+ "testString": "assert(JSX.props.children[1].type === 'p', 'div
应该包含一个p
标签作为第二个元素。');"
},
{
- "text": "The div
should contain a ul
tag as the third element.",
- "testString": "assert(JSX.props.children[2].type === 'ul', 'The div
should contain a ul
tag as the third element.');"
+ "text": "div
应该包含一个ul
标签作为第三个元素。",
+ "testString": "assert(JSX.props.children[2].type === 'ul', 'div
应该包含一个ul
标签作为第三个元素。');"
},
{
- "text": "The div
should contain an h1
tag as the first element.",
- "testString": "assert(JSX.props.children[0].type === 'h1', 'The div
should contain an h1
tag as the first element.');"
+ "text": "div
应该包含一个h1
标签作为第一个元素。",
+ "testString": "assert(JSX.props.children[0].type === 'h1', 'div
应该包含一个h1
标签作为第一个元素。');"
},
{
- "text": "The ul
should contain three li
elements.",
- "testString": "assert(JSX.props.children[2].props.children.length === 3, 'The ul
should contain three li
elements.');"
+ "text": "ul
应该包含三个li
元素。",
+ "testString": "assert(JSX.props.children[2].props.children.length === 3, 'ul
应该包含三个li
元素。');"
}
],
"solutions": [
@@ -127,10 +127,10 @@
"title": "Add Comments in JSX",
"releasedOn": "December 25, 2017",
"description": [
- "JSX is a syntax that gets compiled into valid JavaScript. Sometimes, for readability, you might need to add comments to your code. Like most programming languages, JSX has its own way to do this.",
- "To put comments inside JSX, you use the syntax {/* */}
to wrap around the comment text.",
+ "JSX 是一种可以编译成有效 JavaScript 的语法。有时,为了便于阅读,您可能需要在代码中添加注释。像大多数编程语言一样,JSX 也有自己的方法来实现这一点。",
+ "要将注释放在 JSX 中,可以使用{/* */}
语法来包裹注释文本。",
"div
element, without modifying the existing h1
or p
elements."
+ "代码编辑器中的 JSX 元素与您在上一个挑战中创建的元素类似。在提供的div
元素中的某处添加注释,而不修改现有的h1
或p
元素。"
],
"files": {
"indexjsx": {
@@ -153,20 +153,20 @@
},
"tests": [
{
- "text": "The constant JSX
should return a div
element.",
- "testString": "assert(JSX.type === 'div', 'The constant JSX
should return a div
element.');"
+ "text": "常量JSX
应该返回一个div
元素。",
+ "testString": "assert(JSX.type === 'div', '常量JSX
应该返回一个div
元素。');"
},
{
- "text": "The div
should contain an h1
tag as the first element.",
- "testString": "assert(JSX.props.children[0].type === 'h1', 'The div
should contain an h1
tag as the first element.');"
+ "text": "div
应该包含一个h1
标签作为第一个元素。",
+ "testString": "assert(JSX.props.children[0].type === 'h1', 'div
应该包含一个h1
标签作为第一个元素。');"
},
{
- "text": "The div
should contain a p
tag as the second element.",
- "testString": "assert(JSX.props.children[1].type === 'p', 'The div
should contain a p
tag as the second element.');"
+ "text": "div
应该包含一个p
标签作为第二个元素。",
+ "testString": "assert(JSX.props.children[1].type === 'p', 'div
应该包含一个p
标签作为第二个元素。');"
},
{
- "text": "The JSX
should include a comment.",
- "testString": "getUserInput => assert(getUserInput('index').includes('/*') && getUserInput('index').includes('*/'), 'The JSX
should include a comment.');"
+ "text": "JSX
应该包含一个注释。",
+ "testString": "getUserInput => assert(getUserInput('index').includes('/*') && getUserInput('index').includes('*/'), 'JSX
应该包含一个注释。');"
}
],
"solutions": [
@@ -181,11 +181,11 @@
"title": "Render HTML Elements to the DOM",
"releasedOn": "December 25, 2017",
"description": [
- "So far, you've learned that JSX is a convenient tool to write readable HTML within JavaScript. With React, we can render this JSX directly to the HTML DOM using React's rendering API known as ReactDOM.",
- "ReactDOM offers a simple method to render React elements to the DOM which looks like this: ReactDOM.render(componentToRender, targetNode)
, where the first argument is the React element or component that you want to render, and the second argument is the DOM node that you want to render the component to.",
- "As you would expect, ReactDOM.render()
must be called after the JSX element declarations, just like how you must declare variables before using them.",
+ "到目前为止,您已经了解到 JSX 是一种在 JavaScript 中编写可读 HTML 的便捷工具。使用 React,我们可以使用 React 的渲染 API(ReactDOM)将此 JSX 直接渲染到 HTML DOM。",
+ "ReactDOM 提供了一个简单的方法来将 React 元素呈现给 DOM,如下所示:ReactDOM.render(componentToRender, targetNode)
,其中第一个参数是要渲染的 React 元素或组件,第二个参数是要将组件渲染到的 DOM 节点。",
+ "如你所料,必须在 JSX元素声明之后调用ReactDOM.render()
,就像您在使用变量之前必须声明它一样。",
"ReactDOM.render()
method to render this component to the page. You can pass defined JSX elements directly in as the first argument and use document.getElementById()
to select the DOM node to render them to. There is a div
with id='challenge-node'
available for you to use. Make sure you don't change the JSX
constant."
+ "代码编辑器有一个简单的 JSX 组件。使用ReactDOM.render()
方法将该组件渲染到页面。可以将定义好的 JSX 元素直接作为第一个参数传入,并使用document.getElementById()
来选择要渲染到的 DOM 节点。有一个id='challenge-node'
的div
可供您使用。确保不要更改JSX
常量。"
],
"files": {
"indexjsx": {
@@ -208,20 +208,20 @@
},
"tests": [
{
- "text": "The constant JSX
should return a div
element.",
- "testString": "assert(JSX.type === 'div', 'The constant JSX
should return a div
element.');"
+ "text": "常量JSX
应该返回一个div
元素。",
+ "testString": "assert(JSX.type === 'div', '常量JSX
应该返回一个div
元素。');"
},
{
- "text": "The div
should contain an h1
tag as the first element.",
- "testString": "assert(JSX.props.children[0].type === 'h1', 'The div
should contain an h1
tag as the first element.');"
+ "text": "div
应该包含一个h1
标签作为第一个元素。",
+ "testString": "assert(JSX.props.children[0].type === 'h1', 'div
应该包含一个h1
标签作为第一个元素。');"
},
{
- "text": "The div
should contain a p
tag as the second element.",
- "testString": "assert(JSX.props.children[1].type === 'p', 'The div
should contain a p
tag as the second element.');"
+ "text": "div
应该包含一个p
标签作为第二个元素。",
+ "testString": "assert(JSX.props.children[1].type === 'p', 'div
应该包含一个p
标签作为第二个元素。');"
},
{
- "text": "The provided JSX element should render to the DOM node with id challenge-node
.",
- "testString": "assert(document.getElementById('challenge-node').childNodes[0].innerHTML === 'Lets render this to the DOM
', 'The provided JSX element should render to the DOM node with idchallenge-node
.');"
+ "text": "提供的 JSX 元素应该以 idchallenge-node
渲染到 DOM 节点。",
+ "testString": "assert(document.getElementById('challenge-node').childNodes[0].innerHTML === 'Lets render this to the DOM
', '提供的 JSX 元素应该以 idchallenge-node
渲染到 DOM 节点。');"
}
],
"solutions": [
@@ -236,12 +236,12 @@
"title": "Define an HTML Class in JSX",
"releasedOn": "December 25, 2017",
"description": [
- "Now that you're getting comfortable writing JSX, you may be wondering how it differs from HTML.",
- "So far, it may seem that HTML and JSX are exactly the same.",
- "One key difference in JSX is that you can no longer use the word class
to define HTML classes. This is because class
is a reserved word in JavaScript. Instead, JSX uses className
.",
- "In fact, the naming convention for all HTML attributes and event references in JSX become camelCase. For example, a click event in JSX is onClick
, instead of onclick
. Likewise, onchange
becomes onChange
. While this is a subtle difference, it is an important one to keep in mind moving forward.",
+ "现在您已经习惯了编写 JSX ,您可能想知道它与HTML有什么不同。",
+ "到目前为止,HTML 和 JSX 似乎完全相同。",
+ "JSX 的一个关键区别是你不能再使用class
这个单词来定义 HTML 的 class 名。这是因为class
是 JavaScript 中的保留字。JSX 使用className
代替。",
+ "事实上,JSX 中所有 HTML 属性和事件引用的命名约定都变成了驼峰式。例如,JSX 中的单击事件是 onClick
,而不是 onclick
。同样,onchange
变成了onChange
。虽然这是一个微妙的差异,但重要的是要记住并继续前进。",
"myDiv
to the div
provided in the JSX code."
+ "将 classmyDiv
应用于 JSX 提供的div
上。"
],
"files": {
"indexjsx": {
@@ -263,12 +263,12 @@
},
"tests": [
{
- "text": "The constant JSX
should return a div
element.",
- "testString": "assert.strictEqual(JSX.type, 'div', 'The constant JSX
should return a div
element.');"
+ "text": "常量JSX
应该返回一个div
元素。",
+ "testString": "assert.strictEqual(JSX.type, 'div', '常量JSX
应该返回一个div
元素。');"
},
{
- "text": "The div
has a class of myDiv
.",
- "testString": "assert.strictEqual(JSX.props.className, 'myDiv', 'The div
has a class of myDiv
.');"
+ "text": "div
有一个myDiv
class。",
+ "testString": "assert.strictEqual(JSX.props.className, 'myDiv', 'div
有一个myDiv
class。');"
}
],
"solutions": [
@@ -283,13 +283,13 @@
"title": "Learn About Self-Closing JSX Tags",
"releasedOn": "December 25, 2017",
"description": [
- "So far, you’ve seen how JSX differs from HTML in a key way with the use of className
vs. class
for defining HTML classes.",
- "Another important way in which JSX differs from HTML is in the idea of the self-closing tag.",
- "In HTML, almost all tags have both an opening and closing tag: <div></div>
; the closing tag always has a forward slash before the tag name that you are closing. However, there are special instances in HTML called “self-closing tags”, or tags that don’t require both an opening and closing tag before another tag can start.",
- "For example the line-break tag can be written as <br>
or as <br />
, but should never be written as <br></br>
, since it doesn't contain any content.",
- "In JSX, the rules are a little different. Any JSX element can be written with a self-closing tag, and every element must be closed. The line-break tag, for example, must always be written as <br />
in order to be valid JSX that can be transpiled. A <div>
, on the other hand, can be written as <div />
or <div></div>
. The difference is that in the first syntax version there is no way to include anything in the <div />
. You will see in later challenges that this syntax is useful when rendering React components.",
+ "到目前为止,您已经看到 JSX 与 HTML 的不同之处在于使用className
和使用class
来定义 HTML 的 class。",
+ "JSX 不同于 HTML 的另一个重要方面是自闭合标签。",
+ "在HTML中,几乎所有的标签都有一个开始和结束标签:<div></div>
;结束标签在您要关闭的标签名之前始终具有正斜杠。但是,HTML 中有一些称为“自闭合标签”的特殊实例,它们在另一个标签开始之前,不需要开始和结束标签都存在。",
+ "例如,换行标签可以写成<br>
或者<br />
,但是不应该写成<br></br>
,因为它不包含任何内容。",
+ "在 JSX 中,规则略有不同。任何 JSX 元素都可以使用自闭合标签编写,并且每个元素都必须关闭。例如,换行标签必须始终编写为 <br />
,以便成为有效的可转换的 JSX。另一方面 <div>
可以写成 <div />
或者 <div></div>
。 不同之处在于,在第一个语法版本中,无法在 <div />
中包含任何内容。在后面的挑战中你会发现,这种语法在渲染 React 组件时非常有用。",
"JSX
should return a div
element.",
- "testString": "assert.strictEqual(JSX.type, 'div', 'The constant JSX
should return a div
element.');"
+ "text": "常量JSX
应该返回一个div
元素。",
+ "testString": "assert.strictEqual(JSX.type, 'div', '常量JSX
应该返回一个div
元素。');"
},
{
- "text": "The div
should contain a br
tag.",
- "testString": "assert(Enzyme.shallow(JSX).find('br').length === 1, 'The div
should contain a br
tag.');"
+ "text": "div
应该包含一个br
标签。",
+ "testString": "assert(Enzyme.shallow(JSX).find('br').length === 1, 'div
应该包含一个br
标签。');"
},
{
- "text": "The div
should contain an hr
tag.",
- "testString": "assert(Enzyme.shallow(JSX).find('hr').length === 1, 'The div
should contain an hr
tag.');"
+ "text": "div
应该包含一个hr
标签。",
+ "testString": "assert(Enzyme.shallow(JSX).find('hr').length === 1, 'div
应该包含一个hr
标签。');"
}
],
"solutions": [
@@ -340,14 +340,14 @@
"title": "Create a Stateless Functional Component",
"releasedOn": "December 25, 2017",
"description": [
- "Components are the core of React. Everything in React is a component and here you will learn how to create one.",
- "There are two ways to create a React component. The first way is to use a JavaScript function. Defining a component in this way creates a stateless functional component. The concept of state in an application will be covered in later challenges. For now, think of a stateless component as one that can receive data and render it, but does not manage or track changes to that data. (We'll cover the second way to create a React component in the next challenge.)",
- "To create a component with a function, you simply write a JavaScript function that returns either JSX or null
. One important thing to note is that React requires your function name to begin with a capital letter. Here's an example of a stateless functional component that assigns an HTML class in JSX:",
+ "组件是 React 的核心。React 中的所有内容都是一个组件,在这里您将学习如何创建一个组件。",
+ "有两种方法可以创建 React 组件。第一种方法是使用 JavaScript 函数。以这种方式定义组件会创建无状态功能组件。应用程序中的状态概念将在以后的挑战中介绍。目前,可以将无状态组件视为可以接收数据并对其进行渲染的组件,但是它不管理或跟踪对数据的更改。(我们将在下一次挑战中介绍创建 React 组件的第二种方法。)",
+ "要用函数创建组件,只需编写一个返回 JSX 或null
的 JavaScript 函数。需要注意的一点是,React 要求你的函数名以大写字母开头。下面是一个无状态功能组件的示例,该组件在 JSX 中分配一个 HTML 的 class:",
"// After being transpiled, the <div> will have a CSS class of 'customClass'", - "Because a JSX component represents HTML, you could put several components together to create a more complex HTML page. This is one of the key advantages of the component architecture React provides. It allows you to compose your UI from many separate, isolated components. This makes it easier to build and maintain complex user interfaces.", + "因为 JSX 组件代表 HTML,所以您可以将几个组件放在一起以创建更复杂的 HTML 页面,这是 React 提供的组件架构的关键优势之一,它允许您用许多独立的组件组成 UI。这使得构建和维护复杂的用户界面变得更加容易。", "
const DemoComponent = function() {
return (
<div className='customClass' />
);
};
MyComponent
. Complete this function so it returns a single div
element which contains some string of text.",
- "Note: The text is considered a child of the div
element, so you will not be able to use a self-closing tag."
+ "代码编辑器中有一个名为MyComponent
的函数。完成此函数,使其返回包含一些文本字符串的单个div
元素。",
+ "注意: 文本被视为是div
的子元素,因此您将不能使用自闭合标签。"
],
"files": {
"indexjsx": {
@@ -371,16 +371,16 @@
},
"tests": [
{
- "text": "MyComponent
should return JSX.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.length === 1; })(), 'MyComponent
should return JSX.');"
+ "text": "MyComponent
应该返回 JSX。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.length === 1; })(), 'MyComponent
应该返回 JSX。');"
},
{
- "text": "MyComponent
should return a div
element.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.children().type() === 'div' })(), 'MyComponent
should return a div
element.');"
+ "text": "MyComponent
应该返回一个div
元素。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.children().type() === 'div' })(), 'MyComponent
应该返回一个div
元素。');"
},
{
- "text": "The div
element should contain a string of text.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.find('div').text() !== ''; })(), 'The div
element should contain a string of text.');"
+ "text": "div
元素应该包含一个文本字符串。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.find('div').text() !== ''; })(), 'div
元素应该包含一个文本字符串。');"
}
],
"solutions": [
@@ -395,12 +395,12 @@
"title": "Create a React Component",
"releasedOn": "December 25, 2017",
"description": [
- "The other way to define a React component is with the ES6 class
syntax. In the following example, Kitten
extends React.Component
:",
+ "定义 React 组件的另一种方法是使用 ES6 的class
语法。在以下示例中,Kitten
扩展了React.Component
:",
"class Kitten extends React.Component {", - "This creates an ES6 class
constructor(props) {
super(props);
}
render() {
return (
<h1>Hi</h1>
);
}
}
Kitten
which extends the React.Component
class. So the Kitten
class now has access to many useful React features, such as local state and lifecycle hooks. Don't worry if you aren't familiar with these terms yet, they will be covered in greater detail in later challenges.",
- "Also notice the Kitten
class has a constructor
defined within it that calls super()
. It uses super()
to call the constructor of the parent class, in this case React.Component
. The constructor is a special method used during the initialization of objects that are created with the class
keyword. It is best practice to call a component's constructor
with super
, and pass props
to both. This makes sure the component is initialized properly. For now, know that it is standard for this code to be included. Soon you will see other uses for the constructor as well as props
.",
+ "这将创建一个 ES6类Kitten
,它扩展了React.Component
类。因此,Kitten
类现在可以访问许多有用的 React 功能,例如本地状态和生命周期钩子。如果您还不熟悉这些术语,请不要担心,在以后的挑战中我们将更详细地介绍它们。",
+ "另请注意,Kitten
类中定义了一个调用super()
方法的constructor
。它使用super()
调用父类的构造函数,即本例中的React.Component
。构造函数是使用class
关键字创建的特殊方法,它用在对象初始化期间。最佳做法是使用super
调用组件的constructor
,并将props
传递给它们,这可确保组件正确初始化。现在,你只需要知道包含的这些代码都是标准的。很快你会看到构造函数的其他用途以及props
。",
"MyComponent
is defined in the code editor using class syntax. Finish writing the render
method so it returns a div
element that contains an h1
with the text Hello React!
."
+ "MyComponent
是使用类语法在代码编辑器中定义的。完成render
方法的编写,使其返回div
元素,其中包含文本内容为Hello React!
的h1
元素。"
],
"files": {
"indexjsx": {
@@ -430,16 +430,16 @@
},
"tests": [
{
- "text": "The React component should return a div
element.",
- "testString": "assert(Enzyme.shallow(React.createElement(MyComponent)).type() === 'div', 'The React component should return a div
element.');"
+ "text": "该 React 组件应该返回一个div
元素。",
+ "testString": "assert(Enzyme.shallow(React.createElement(MyComponent)).type() === 'div', '该 React 组件应该返回一个div
元素。');"
},
{
- "text": "The returned div
should render an h1
header within it.",
- "testString": "assert(/div
should render an h1
header within it.');"
+ "text": "返回的div
中应该渲染一个h1
标题。",
+ "testString": "assert(/div
中应该渲染一个h1
标题。');"
},
{
- "text": "The h1
header should contain the string Hello React!
.",
- "testString": "assert(Enzyme.shallow(React.createElement(MyComponent)).html() === 'h1
header should contain the string Hello React!
.');"
+ "text": "h1
标题中应该包含字符串Hello React!
。",
+ "testString": "assert(Enzyme.shallow(React.createElement(MyComponent)).html() === 'h1
标题中应该包含字符串Hello React!
。');"
}
],
"solutions": [
@@ -454,13 +454,13 @@
"title": "Create a Component with Composition",
"releasedOn": "December 25, 2017",
"description": [
- "Now we will look at how we can compose multiple React components together. Imagine you are building an App and have created three components, a Navbar
, Dashboard
, and Footer
.",
- "To compose these components together, you could create an App
parent component which renders each of these three components as children. To render a component as a child in a React component, you include the component name written as a custom HTML tag in the JSX. For example, in the render
method you could write:",
+ "现在我们来看看如何组合多个 React 组件。想象一下,您正在构建一个应用程序,并创建了三个组件:Navbar
、Dashboard
和Footer
。",
+ "要将这些组件组合在一起,您可以创建一个App
父组件,将这三个组件分别渲染成为子组件。要在 React 组件中渲染一个子组件,您需要在 JSX 中包含作为自定义 HTML 标签编写的组件名称。例如,在render
方法中,您可以这样编写:",
"return (", - "When React encounters a custom HTML tag that references another component (a component name wrapped in
<App>
<Navbar />
<Dashboard />
<Footer />
</App>
)
< />
like in this example), it renders the markup for that component in the location of the tag. This should illustrate the parent/child relationship between the App
component and the Navbar
, Dashboard
, and Footer
.",
+ "当 React 遇到引用另一个组件的自定义 HTML 标签时(如本例所示,组件名称包含在< />
中),它在标签的位置渲染该组件的标签。这可以说明App
组件和Navbar
、Dashboard
以及Footer
>之间的父/子关系。",
"ChildComponent
and a React component called ParentComponent
. Compose the two together by rendering the ChildComponent
within the ParentComponent
. Make sure to close the ChildComponent
tag with a forward slash.",
- "Note: ChildComponent
is defined with an ES6 arrow function because this is a very common practice when using React. However, know that this is just a function. If you aren't familiar with the arrow function syntax, please refer to the JavaScript section."
+ "在代码编辑器中,有一个名为ChildComponent
的简单功能组件和一个名为ParentComponent
的 React 组件。通过在ParentComponent
中渲染ChildComponent
来将两者组合在一起。确保使用正斜杠关闭ChildComponent
标签。",
+ "注意: ChildComponent
是使用 ES6 的箭头函数定义的,因为这是使用 React 时非常常见的做法。但是,要知道这只是一个函数。如果您不熟悉箭头函数语法,请参阅 JavaScript 部分。"
],
"files": {
"indexjsx": {
@@ -501,16 +501,16 @@
},
"tests": [
{
- "text": "The React component should return a single div
element.",
- "testString": "assert((function() { var shallowRender = Enzyme.shallow(React.createElement(ParentComponent)); return shallowRender.type() === 'div'; })(), 'The React component should return a single div
element.');"
+ "text": "React 组件应该返回单个div
元素。",
+ "testString": "assert((function() { var shallowRender = Enzyme.shallow(React.createElement(ParentComponent)); return shallowRender.type() === 'div'; })(), 'React 组件应该返回单个div
元素。');"
},
{
- "text": "The component should return two nested elements.",
- "testString": "assert((function() { var shallowRender = Enzyme.shallow(React.createElement(ParentComponent)); return shallowRender.children().length === 2; })(), 'The component should return two nested elements.');"
+ "text": "组件应该返回两个嵌套的元素。",
+ "testString": "assert((function() { var shallowRender = Enzyme.shallow(React.createElement(ParentComponent)); return shallowRender.children().length === 2; })(), '组件应该返回两个嵌套的元素。');"
},
{
- "text": "The component should return the ChildComponent as its second child.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ParentComponent)); return mockedComponent.find('ParentComponent').find('ChildComponent').length === 1; })(), 'The component should return the ChildComponent as its second child.');"
+ "text": "组件的第二个子元素应该是 ChildComponent。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ParentComponent)); return mockedComponent.find('ParentComponent').find('ChildComponent').length === 1; })(), '组件的第二个子元素应该是 ChildComponent。');"
}
],
"solutions": [
@@ -525,10 +525,10 @@
"title": "Use React to Render Nested Components",
"releasedOn": "December 25, 2017",
"description": [
- "The last challenge showed a simple way to compose two components, but there are many different ways you can compose components with React.",
- "Component composition is one of React's powerful features. When you work with React, it is important to start thinking about your user interface in terms of components like the App example in the last challenge. You break down your UI into its basic building blocks, and those pieces become the components. This helps to separate the code responsible for the UI from the code responsible for handling your application logic. It can greatly simplify the development and maintenance of complex projects.",
+ "上一个挑战显示了组合两个组件的简单方法,但是有许多不同的方法可以把 React 组件组合在一起。",
+ "组件组合是 React 的强大功能之一。当您使用 React 时,先考虑您的用户界面的组件构成很重要(如上一个挑战中的 App 示例)。您将UI分解为基本的构建块,这些块就变成了组件。这有助于将负责 UI 的代码与负责处理应用程序逻辑的代码分开,并可以大大简化复杂项目的开发和维护。",
"TypesOfFruit
and Fruits
. Take the TypesOfFruit
component and compose it, or nest it, within the Fruits
component. Then take the Fruits
component and nest it within the TypesOfFood
component. The result should be a child component, nested within a parent component, which is nested within a parent component of its own!"
+ "代码编辑器中定义了两个功能组件,分别是TypesOfFruit
和Fruits
。取TypesOfFruit
组件,并在Fruits
组件中嵌套它。然后将Fruits
组件嵌套到TypesOfFood
组件中。结果应该是子组件嵌套在父组件中,父组件嵌套在父组件的父组件中!"
],
"files": {
"indexjsx": {
@@ -585,20 +585,20 @@
},
"tests": [
{
- "text": "The TypesOfFood
component should return a single div
element.",
- "testString": "assert(Enzyme.shallow(React.createElement(TypesOfFood)).type() === 'div', 'The TypesOfFood
component should return a single div
element.');"
+ "text": "TypesOfFood
组件应该返回单个div
元素。",
+ "testString": "assert(Enzyme.shallow(React.createElement(TypesOfFood)).type() === 'div', 'TypesOfFood
组件应该返回单个div
元素。');"
},
{
- "text": "The TypesOfFood
component should return the Fruits
component.",
- "testString": "assert(Enzyme.shallow(React.createElement(TypesOfFood)).props().children[1].type.name === 'Fruits', 'The TypesOfFood
component should return the Fruits
component.');"
+ "text": "TypesOfFood
组件应该返回Fruits
组件。",
+ "testString": "assert(Enzyme.shallow(React.createElement(TypesOfFood)).props().children[1].type.name === 'Fruits', 'TypesOfFood
组件应该返回Fruits
组件。');"
},
{
- "text": "The Fruits
component should return the TypesOfFruit
component.",
- "testString": "assert(Enzyme.mount(React.createElement(TypesOfFood)).find('h2').html() === 'Fruits
component should return the TypesOfFruit
component.');"
+ "text": "Fruits
组件应该返回TypesOfFruit
组件。",
+ "testString": "assert(Enzyme.mount(React.createElement(TypesOfFood)).find('h2').html() === 'Fruits
组件应该返回TypesOfFruit
组件。');"
},
{
- "text": "The TypesOfFruit
component should return the h2
and ul
elements.",
- "testString": "assert(Enzyme.mount(React.createElement(TypesOfFood)).find('ul').text() === 'ApplesBlueberriesStrawberriesBananas', 'The TypesOfFruit
component should return the h2
and ul
elements.');"
+ "text": "TypesOfFruit
组件应该返回h2
和ul
元素。",
+ "testString": "assert(Enzyme.mount(React.createElement(TypesOfFood)).find('ul').text() === 'ApplesBlueberriesStrawberriesBananas', 'TypesOfFruit
组件应该返回h2
和ul
元素。');"
}
],
"solutions": [
@@ -613,10 +613,10 @@
"title": "Compose React Components",
"releasedOn": "December 25, 2017",
"description": [
- "As the challenges continue to use more complex compositions with React components and JSX, there is one important point to note. Rendering ES6 style class components within other components is no different than rendering the simple components you used in the last few challenges. You can render JSX elements, stateless functional components, and ES6 class components within other components.",
+ "随着挑战继续,我们将组合使用更复杂的 React组件 和 JSX,有一点需要注意。在其他组件中渲染 ES6 风格的类组件和渲染您在过去几个挑战中使用的简单组件没有什么不同。您可以在其他组件中渲染 JSX 元素、无状态功能组件和 ES6 类组件。",
"TypesOfFood
component is already rendering a component called Vegetables
. Also, there is the Fruits
component from the last challenge.",
- "Nest two components inside of Fruits
— first NonCitrus
, and then Citrus
. Both of these components are provided for you in the background. Next, nest the Fruits
class component into the TypesOfFood
component, below the h1
header and above Vegetables
. The result should be a series of nested components, which uses two different component types."
+ "在代码编辑器中,TypesOfFood
组件已经渲染了一个名为Vegetables
的组件。此外,还有上次挑战中的Fruits
组件。",
+ "在Fruits
中嵌套两个组件,首先NonCitrus
,然后是Citrus
,这两个组件都是在后台为您提供的。接下来,将Fruits
类组件嵌到TypesOfFood
组件中,位于h1
标题下方和Vegetables
上方。结果应该是一系列嵌套的组件,它们使用两种不同的组件类型。"
],
"files": {
"indexjsx": {
@@ -710,20 +710,20 @@
},
"tests": [
{
- "text": "The TypesOfFood
component should return a single div
element.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().type() === 'div'; })(), 'The TypesOfFood
component should return a single div
element.');"
+ "text": "TypesOfFood
组件应该返回单个div
元素。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().type() === 'div'; })(), 'TypesOfFood
组件应该返回单个div
元素。');"
},
{
- "text": "The TypesOfFood
component should return the Fruits
component.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().childAt(1).name() === 'Fruits'; })(), 'The TypesOfFood
component should return the Fruits
component.');"
+ "text": "TypesOfFood
组件应该返回Fruits
组件。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().childAt(1).name() === 'Fruits'; })(), 'TypesOfFood
组件应该返回Fruits
组件。');"
},
{
- "text": "The Fruits
component should return the NonCitrus
component and the Citrus
component.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return (mockedComponent.find('Fruits').children().find('NonCitrus').length === 1 && mockedComponent.find('Fruits').children().find('Citrus').length === 1); })(), 'The Fruits
component should return the NonCitrus
component and the Citrus
component.');"
+ "text": "Fruits
组件应该返回NonCitrus
组件和Citrus
组件。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return (mockedComponent.find('Fruits').children().find('NonCitrus').length === 1 && mockedComponent.find('Fruits').children().find('Citrus').length === 1); })(), 'Fruits
组件应该返回NonCitrus
组件和Citrus
组件。');"
},
{
- "text": "The TypesOfFood
component should return the Vegetables
component below the Fruits
component.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().childAt(2).name() === 'Vegetables'; })(), 'The TypesOfFood
component should return the Vegetables
component below the Fruits
component.');"
+ "text": "TypesOfFood
组件应该返回Vegetables
组件,且其位于Fruits
组件之下。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().childAt(2).name() === 'Vegetables'; })(), 'TypesOfFood
组件应该返回Vegetables
组件,且其位于Fruits
组件之下。');"
}
],
"solutions": [
@@ -738,11 +738,11 @@
"title": "Render a Class Component to the DOM",
"releasedOn": "December 25, 2017",
"description": [
- "You may remember using the ReactDOM API in an earlier challenge to render JSX elements to the DOM. The process for rendering React components will look very similar. The past few challenges focused on components and composition, so the rendering was done for you behind the scenes. However, none of the React code you write will render to the DOM without making a call to the ReactDOM API.",
- "Here's a refresher on the syntax: ReactDOM.render(componentToRender, targetNode)
. The first argument is the React component that you want to render. The second argument is the DOM node that you want to render that component within.",
- "React components are passed into ReactDOM.render()
a little differently than JSX elements. For JSX elements, you pass in the name of the element that you want to render. However, for React components, you need to use the same syntax as if you were rendering a nested component, for example ReactDOM.render(<ComponentToRender />, targetNode)
. You use this syntax for both ES6 class components and functional components.",
+ "您可能还记得在早期挑战中使用 ReactDOM API 将 JSX 元素渲染到 DOM,渲染 React 组件的过程看起来非常相似。过去的几个挑战主要针对组件和组合,因此渲染是在幕后为您完成的。但是,如果不调用 ReactDOM API,您编写的任何 React 代码都不会渲染到 DOM。",
+ "以下是语法的复习:ReactDOM.render(componentToRender, targetNode)
。第一个参数是要渲染的 React 组件。第二个参数是要在其中渲染该组件的 DOM 节点。",
+ "React 组件传递到ReactDOM.render()
与 JSX 元素略有不同。对于 JSX 元素,您传入的是要渲染的元素的名称。但是,对于 React 组件,您需要使用与渲染嵌套组件相同的语法,例如ReactDOM.render(<ComponentToRender />, targetNode)
。您可以将此语法用于ES6类组件和函数组件。",
"Fruits
and Vegetables
components are defined for you behind the scenes. Render both components as children of the TypesOfFood
component, then render TypesOfFood
to the DOM. There is a div
with id='challenge-node'
available for you to use."
+ "在后台为您定义了Fruits
和Vegetables
组件。将两个组件渲染为TypesOfFood
组件的子组件,然后将TypesOfFood
渲染到 DOM。有一个id='challenge-node'
的div
可供您使用。"
],
"files": {
"indexjsx": {
@@ -812,20 +812,20 @@
},
"tests": [
{
- "text": "The TypesOfFood
component should return a single div
element.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().type() === 'div'; })(), 'The TypesOfFood
component should return a single div
element.');"
+ "text": "TypesOfFood
组件应该返回单个div
元素。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().type() === 'div'; })(), 'TypesOfFood
组件应该返回单个div
元素。');"
},
{
- "text": "The TypesOfFood
component should render the Fruits
component after the h1
element.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().childAt(1).name() === 'Fruits'; })(), 'The TypesOfFood
component should render the Fruits
component after the h1
element.');"
+ "text": "TypesOfFood
组件应该在h1
元素之后渲染Fruits
组件。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().childAt(1).name() === 'Fruits'; })(), 'TypesOfFood
组件应该在h1
元素之后渲染Fruits
组件。');"
},
{
- "text": "The TypesOfFood
component should render the Vegetables
component after Fruits
.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().childAt(2).name() === 'Vegetables'; })(), 'The TypesOfFood
component should render the Vegetables
component after Fruits
.');"
+ "text": "TypesOfFood
组件应该在Fruits
组件之后渲染Vegetables
组件。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(TypesOfFood)); return mockedComponent.children().childAt(2).name() === 'Vegetables'; })(), 'TypesOfFood
组件应该在Fruits
组件之后渲染Vegetables
组件。');"
},
{
- "text": "The TypesOfFood
component should render to the DOM within the div
with the id challenge-node
.",
- "testString": "assert((function() { const html = document.getElementById('challenge-node').childNodes[0].innerHTML; return (html === 'TypesOfFood
component should render to the DOM within the div
with the id challenge-node
.');"
+ "text": "TypesOfFood
组件应该在 id 为challenge-node
的div
中渲染到 DOM。",
+ "testString": "assert((function() { const html = document.getElementById('challenge-node').childNodes[0].innerHTML; return (html === 'TypesOfFood
组件应该在 id 为challenge-node
的div
中渲染到 DOM。');"
}
],
"solutions": [
@@ -840,10 +840,10 @@
"title": "Write a React Component from Scratch",
"releasedOn": "December 25, 2017",
"description": [
- "Now that you've learned the basics of JSX and React components, it's time to write a component on your own. React components are the core building blocks of React applications so it's important to become very familiar with writing them. Remember, a typical React component is an ES6 class
which extends React.Component
. It has a render method that returns HTML (from JSX) or null
. This is the basic form of a React component. Once you understand this well, you will be prepared to start building more complex React projects.",
+ "现在您已经了解了 JSX 和 React 组件的基础知识,现在是时候自己编写一个组件了。React 组件是 React 应用程序的核心组成部分,因此熟练编写它们是非常重要的。记住,典型的 React 组件是 ES6class
,它扩展了React.Component
。它有一个返回HTML(从 JSX 返回)或null
的渲染方法,这是 React 组件的基本形式。一旦你深刻地理解了这一点,你就可以开始构建更复杂的 React 项目了。",
"MyComponent
that extends React.Component
. Its render method should return a div
that contains an h1
tag with the text: My First React Component!
in it. Use this text exactly, the case and punctuation matter. Make sure to call the constructor for your component, too.",
- "Render this component to the DOM using ReactDOM.render()
. There is a div
with id='challenge-node'
available for you to use."
+ "定义一个MyComponent
类,它是的React.Component
扩展。它的渲染方法应该返回一个div
,其中包含一个h1
标签,标签文本为:My First React Component!
。正确使用文本、大小写和标点符号,并确保调用组件的构造函数。",
+ "使用ReactDOM.render()
把该组件渲染到 DOM 中。有一个id='challenge-node'
的div
可供您使用。"
],
"files": {
"indexjsx": {
@@ -860,16 +860,16 @@
},
"tests": [
{
- "text": "There should be a React component called MyComponent
.",
- "testString": "getUserInput => assert(getUserInput('index').replace(/\\s/g, '').includes('classMyComponentextendsReact.Component{'), 'There should be a React component called MyComponent
.');"
+ "text": "应该有一个名为MyComponent
的React组件。",
+ "testString": "getUserInput => assert(getUserInput('index').replace(/\\s/g, '').includes('classMyComponentextendsReact.Component{'), '应该有一个名为MyComponent
的React组件。');"
},
{
- "text": "MyComponent
should contain an h1
tag with text My First React Component!
Case and punctuation matter.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.find('h1').text() === 'My First React Component!'; })(), 'MyComponent
should contain an h1
tag with text My First React Component!
Case and punctuation matter.');"
+ "text": "MyComponent
应该包含一个h1
标签,标签的文本为My First React Component!
,区分大小写并有标点符号。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.find('h1').text() === 'My First React Component!'; })(), 'MyComponent
应该包含一个h1
标签,标签的文本为My First React Component!
,区分大小写并有标点符号。');"
},
{
- "text": "MyComponent
should render to the DOM.",
- "testString": "assert(document.getElementById('challenge-node').childNodes.length === 1, 'MyComponent
should render to the DOM.');"
+ "text": "MyComponent
应该渲染到 DOM。",
+ "testString": "assert(document.getElementById('challenge-node').childNodes.length === 1, 'MyComponent
应该渲染到 DOM。');"
}
],
"solutions": [
@@ -884,13 +884,13 @@
"title": "Pass Props to a Stateless Functional Component",
"releasedOn": "December 25, 2017",
"description": [
- "The previous challenges covered a lot about creating and composing JSX elements, functional components, and ES6 style class components in React. With this foundation, it's time to look at another feature very common in React: props. In React, you can pass props, or properties, to child components. Say you have an App
component which renders a child component called Welcome
that is a stateless functional component. You can pass Welcome
a user
property by writing:",
+ "之前的挑战涵盖了关于在 React 中创建和组合 JSX 元素、函数组件和 ES6 风格的类组件的很多内容。有了这个基础,现在是时候看看 React 中的另一个常见特性 props 了。在 React 中,您可以将属性传递给子组件。假设您有一个App
组件,该组件渲染了一个名为Welcome
的子组件,它是一个无状态函数组件。您可以通过以下方式给Welcome
传递一个user
属性:",
"<App>", - "You use custom HTML attributes that React provides support for to pass the property
<Welcome user='Mark' />
</App>
user
to the component Welcome
. Since Welcome
is a stateless functional component, it has access to this value like so:",
+ "使用自定义 HTML 属性,React 支持将属性user
传递给组件Welcome
。由于Welcome
是一个无状态函数组件,它可以像这样访问该值:",
"const Welcome = (props) => <h1>Hello, {props.user}!</h1>", - "It is standard to call this value
props
and when dealing with stateless functional components, you basically consider it as an argument to a function which returns JSX. You can access the value of the argument in the function body. With class components, you will see this is a little different.",
+ "调用props
这个值是标准的,当处理无状态函数组件时,您基本上可以将其视为返回 JSX 的函数的参数,您可以在函数体中访问参数的值。对于类组件,您将看到这有点不同。",
"Calendar
and CurrentDate
components in the code editor. When rendering CurrentDate
from the Calendar
component, pass in a property of date
assigned to the current date from JavaScript's Date
object. Then access this prop
in the CurrentDate
component, showing its value within the p
tags. Note that for prop
values to be evaluated as JavaScript, they must be enclosed in curly brackets, for instance date={Date()}
."
+ "代码编辑器中有Calendar
和CurrentDate
组件。从Calendar
组件渲染CurrentDate
时,从JavaScript的Date
对象分配当前日期,并将其作为date
属性传入。然后访问CurrentDate
组件的prop
,并在p
标签中显示其值。请注意,要将prop
的值视为JavaScript,必须将它们括在大括号中,例如date={Date()}
。"
],
"files": {
"indexjsx": {
@@ -933,24 +933,24 @@
},
"tests": [
{
- "text": "The Calendar
component should return a single div
element.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); return mockedComponent.children().type() === 'div'; })(), 'The Calendar
component should return a single div
element.');"
+ "text": "Calendar
组件应该返回单个div
元素。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); return mockedComponent.children().type() === 'div'; })(), 'Calendar
组件应该返回单个div
元素。');"
},
{
- "text": "The second child of the Calendar
component should be the CurrentDate
component.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); return mockedComponent.children().childAt(1).name() === 'CurrentDate'; })(), 'The second child of the Calendar
component should be the CurrentDate
component.');"
+ "text": "Calendar
组件的第二个子元素应该是CurrentDate
组件。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); return mockedComponent.children().childAt(1).name() === 'CurrentDate'; })(), 'Calendar
组件的第二个子元素应该是CurrentDate
组件。');"
},
{
- "text": "The CurrentDate
component should have a prop called date
.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); return mockedComponent.children().childAt(1).props().date })(), 'The CurrentDate
component should have a prop called date
.');"
+ "text": "CurrentDate
组件应该有一个名为date
的属性。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); return mockedComponent.children().childAt(1).props().date })(), 'CurrentDate
组件应该有一个名为date
的属性。');"
},
{
- "text": "The date
prop of the CurrentDate
should contain a string of text.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); const prop = mockedComponent.children().childAt(1).props().date; return( typeof prop === 'string' && prop.length > 0 ); })(), 'The date
prop of the CurrentDate
should contain a string of text.');"
+ "text": "CurrentDate
的date
属性应该包含一段文本字符串。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); const prop = mockedComponent.children().childAt(1).props().date; return( typeof prop === 'string' && prop.length > 0 ); })(), 'CurrentDate
的date
属性应该包含一段文本字符串。');"
},
{
- "text": "The CurrentDate
component should render the value from the date
prop in the p
tag.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); return mockedComponent.find('p').html().includes(Date().substr(3)); })(), 'The CurrentDate
component should render the value from the date
prop in the p
tag.');"
+ "text": "CurrentDate
组件应该把date
属性渲染在p
标签内。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); return mockedComponent.find('p').html().includes(Date().substr(3)); })(), 'CurrentDate
组件应该把date
属性渲染在p
标签内。');"
}
],
"solutions": [
@@ -965,15 +965,15 @@
"title": "Pass an Array as Props",
"releasedOn": "December 25, 2017",
"description": [
- "The last challenge demonstrated how to pass information from a parent component to a child component as props
or properties. This challenge looks at how arrays can be passed as props
. To pass an array to a JSX element, it must be treated as JavaScript and wrapped in curly braces.",
+ "上一个挑战演示了如何将来自父组件的信息作为props
传递给子组件。这个挑战着眼于如何将数组作为props
传递。要将数组传递给 JSX 元素,必须将其视为 JavaScript 并用花括号括起来。",
"<ParentComponent>", - "The child component then has access to the array property
<ChildComponent colors={[\"green\", \"blue\", \"red\"]} />
</ParentComponent>
colors
. Array methods such as join()
can be used when accessing the property.",
+ "然后子组件可以访问数组属性colors
。访问属性时可以使用join()
等数组方法。",
"const ChildComponent = (props) => <p>{props.colors.join(', ')}</p>
",
- "This will join all colors
array items into a comma separated string and produce:",
+ "这将把所有colors
数组项连接成一个逗号分隔的字符串并生成:",
" <p>green, blue, red</p>
",
- "Later, we will learn about other common methods to render arrays of data in React.",
+ "稍后,我们将了解在 React 中渲染数据数组的其他常用方法。",
"List
and ToDo
components in the code editor. When rendering each List
from the ToDo
component, pass in a tasks
property assigned to an array of to-do tasks, for example [\"walk dog\", \"workout\"]
. Then access this tasks
array in the List
component, showing its value within the p
element. Use join(\", \")
to display the props.tasks
array in the p
element as a comma separated list. Today's list should have at least 2 tasks and tomorrow's should have at least 3 tasks."
+ "代码编辑器中有List
和ToDo
组件。在ToDo
组件中渲染每个List
时,传入tasks
属性并将其分配给待办任务数组,例如[\"walk dog\", \"workout\"]
。然后访问List
组件中的tasks
数组,在p
元素中显示其值。使用join(\", \")
把props.tasks
数组作为逗号分隔列表显示在p
元素中。今天的列表应该至少有2个任务,明天应该至少有3个任务。"
],
"files": {
"indexjsx": {
@@ -1014,32 +1014,32 @@
},
"tests": [
{
- "text": "The ToDo
component should return a single outer div
.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.children().first().type() === 'div'; })(), 'The ToDo
component should return a single outer div
.');"
+ "text": "ToDo
组件应该返回单个外部div
。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.children().first().type() === 'div'; })(), 'ToDo
组件应该返回单个外部div
。');"
},
{
- "text": "The third child of the ToDo
component should be an instance of the List
component.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.children().first().childAt(2).name() === 'List'; })(), 'The third child of the ToDo
component should be an instance of the List
component.');"
+ "text": "ToDo
组件的第三个子元素应该是List
组件的一个实例。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.children().first().childAt(2).name() === 'List'; })(), 'ToDo
组件的第三个子元素应该是List
组件的一个实例。');"
},
{
- "text": "The fifth child of the ToDo
component should be an instance of the List
component.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.children().first().childAt(4).name() === 'List'; })(), 'The fifth child of the ToDo
component should be an instance of the List
component.');"
+ "text": "ToDo
组件的第五个子元素应该是List
组件的一个实例。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.children().first().childAt(4).name() === 'List'; })(), 'ToDo
组件的第五个子元素应该是List
组件的一个实例。');"
},
{
- "text": "Both instances of the List
component should have a property called tasks
and tasks
should be of type array.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return Array.isArray(mockedComponent.find('List').get(0).props.tasks) && Array.isArray(mockedComponent.find('List').get(1).props.tasks); })(), 'Both instances of the List
component should have a property called tasks
and tasks
should be of type array.');"
+ "text": "List
组件的两个实例都应该具有一个名为tasks
的属性,并且tasks
的类型应该是数组。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return Array.isArray(mockedComponent.find('List').get(0).props.tasks) && Array.isArray(mockedComponent.find('List').get(1).props.tasks); })(), 'List
组件的两个实例都应该具有一个名为tasks
的属性,并且tasks
的类型应该是数组。');"
},
{
- "text": "The first List
component representing the tasks for today should have 2 or more items.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.find('List').get(0).props.tasks.length >= 2; })(), 'The first List
component representing the tasks for today should have 2 or more items.');"
+ "text": "表示今天任务的第一个List
组件应该有 2 个或更多项。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.find('List').get(0).props.tasks.length >= 2; })(), '表示今天任务的第一个List
组件应该有 2 个或更多项。');"
},
{
- "text": "The second List
component representing the tasks for tomorrow should have 3 or more items.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.find('List').get(1).props.tasks.length >= 3; })(), 'The second List
component representing the tasks for tomorrow should have 3 or more items.');"
+ "text": "表示明天任务的第二个List
组件应该有 3 个或更多项。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.find('List').get(1).props.tasks.length >= 3; })(), '表示明天任务的第二个List
组件应该有 3 个或更多项。');"
},
{
- "text": "The List
component should render the value from the tasks
prop in the p
tag.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.find('p').get(0).props.children === mockedComponent.find('List').get(0).props.tasks.join(', ') && mockedComponent.find('p').get(1).props.children === mockedComponent.find('List').get(1).props.tasks.join(', '); })(), 'The List
component should render the value from the tasks
prop in the p
tag.');"
+ "text": "List
组件应在p
标签中渲染tasks
属性的值。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ToDo)); return mockedComponent.find('p').get(0).props.children === mockedComponent.find('List').get(0).props.tasks.join(', ') && mockedComponent.find('p').get(1).props.children === mockedComponent.find('List').get(1).props.tasks.join(', '); })(), 'List
组件应在p
标签中渲染tasks
属性的值。');"
}
],
"solutions": [
@@ -1056,7 +1056,7 @@
"description": [
"React also has an option to set default props. You can assign default props to a component as a property on the component itself and React assigns the default prop if necessary. This allows you to specify what a prop value should be if no value is explicitly provided. For example, if you declare MyComponent.defaultProps = { location: 'San Francisco' }
, you have defined a location prop that's set to the string San Francisco
, unless you specify otherwise. React assigns default props if props are undefined, but if you pass null
as the value for a prop, it will remain null
.",
"ShoppingCart
component. Define default props on this component which specify a prop items
with a value of 0
."
+ "The code editor shows a ShoppingCart
组件。 Define default props on this component which specify a prop items
with a value of 0
."
],
"files": {
"indexjsx": {
@@ -1102,7 +1102,7 @@
"title": "Override Default Props",
"releasedOn": "December 25, 2017",
"description": [
- "The ability to set default props is a useful feature in React. The way to override the default props is to explicitly set the prop values for a component.",
+ "The ability to set default props is a useful feature in React. The way to override the default props is to explicitly set the prop values for a组件。",
"ShoppingCart
component now renders a child component Items
. This Items
component has a default prop quantity
set to the integer 0
. Override the default prop by passing in a value of 10
for quantity
.",
"Note: Remember that the syntax to add a prop to a component looks similar to how you add HTML attributes. However, since the value for quantity
is an integer, it won't go in quotes but it should be wrapped in curly braces. For example, {100}
. This syntax tells JSX to interpret the value within the braces directly as JavaScript."
@@ -1148,8 +1148,8 @@
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ShoppingCart)); return mockedComponent.find('Items').length === 1; })(), 'The component Items
should render.');"
},
{
- "text": "The Items
component should have a prop of { quantity: 10 }
passed from the ShoppingCart
component.",
- "testString": "getUserInput => assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ShoppingCart)); return mockedComponent.find('Items').props().quantity == 10 && getUserInput('index').replace(/ /g,'').includes('Items
component should have a prop of { quantity: 10 }
passed from the ShoppingCart
component.');"
+ "text": "The Items
component should have a prop of { quantity: 10 }
passed from the ShoppingCart
组件。",
+ "testString": "getUserInput => assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ShoppingCart)); return mockedComponent.find('Items').props().quantity == 10 && getUserInput('index').replace(/ /g,'').includes('Items
component should have a prop of { quantity: 10 }
passed from the ShoppingCart
组件。');"
}
],
"solutions": [
@@ -1167,7 +1167,7 @@
"React provides useful type-checking features to verify that components receive props of the correct type. For example, your application makes an API call to retrieve data that you expect to be in an array, which is then passed to a component as a prop. You can set propTypes
on your component to require the data to be of type array
. This will throw a useful warning when the data is of any other type.",
"It's considered a best practice to set propTypes
when you know the type of a prop ahead of time. You can define a propTypes
property for a component in the same way you defined defaultProps
. Doing this will check that props of a given key are present with a given type. Here's an example to require the type function
for a prop called handleClick
:",
"MyComponent.propTypes = { handleClick: PropTypes.func.isRequired }
",
- "In the example above, the PropTypes.func
part checks that handleClick
is a function. Adding isRequired
tells React that handleClick
is a required property for that component. You will see a warning if that prop isn't provided. Also notice that func
represents function
. Among the seven JavaScript primitive types, function
and boolean
(written as bool
) are the only two that use unusual spelling. In addition to the primitive types, there are other types available. For example, you can check that a prop is a React element. Please refer to the documentation for all of the options.",
+ "In the example above, the PropTypes.func
part checks that handleClick
is a function. Adding isRequired
tells React that handleClick
is a required property for that组件。 You will see a warning if that prop isn't provided. Also notice that func
represents function
. Among the seven JavaScript primitive types, function
and boolean
(written as bool
) are the only two that use unusual spelling. In addition to the primitive types, there are other types available. For example, you can check that a prop is a React元素。 Please refer to the documentation for all of the options.",
"Note: As of React v15.5.0, PropTypes
is imported independently from React, like this:",
"import React, { PropTypes } from 'react';
",
"ResetPassword
component should return a single div
element.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ResetPassword)); return mockedComponent.children().type() === 'div'; })(), 'The ResetPassword
component should return a single div
element.');"
+ "text": "The ResetPassword
component应该返回单个div
元素。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ResetPassword)); return mockedComponent.children().type() === 'div'; })(), 'The ResetPassword
component应该返回单个div
元素。');"
},
{
- "text": "The fourth child of ResetPassword
should be the ReturnTempPassword
component.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ResetPassword)); return mockedComponent.children().childAt(3).name() === 'ReturnTempPassword'; })(), 'The fourth child of ResetPassword
should be the ReturnTempPassword
component.');"
+ "text": "The fourth child of ResetPassword
should be the ReturnTempPassword
组件。",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ResetPassword)); return mockedComponent.children().childAt(3).name() === 'ReturnTempPassword'; })(), 'The fourth child of ResetPassword
should be the ReturnTempPassword
组件。');"
},
{
- "text": "The ReturnTempPassword
component should have a prop called tempPassword
.",
- "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ResetPassword)); return mockedComponent.find('ReturnTempPassword').props().tempPassword; })(), 'The ReturnTempPassword
component should have a prop called tempPassword
.');"
+ "text": "The ReturnTempPassword
组件应该有一个名为的属性tempPassword
.",
+ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ResetPassword)); return mockedComponent.find('ReturnTempPassword').props().tempPassword; })(), 'The ReturnTempPassword
组件应该有一个名为的属性tempPassword
.');"
},
{
"text": "The tempPassword
prop of ReturnTempPassword
should be equal to a string of at least 8
characters.",
@@ -1397,7 +1397,7 @@
"One of the most important topics in React is state
. State consists of any data your application needs to know about, that can change over time. You want your apps to respond to state changes and present an updated UI when necessary. React offers a nice solution for the state management of modern web applications.",
"You create state in a React component by declaring a state
property on the component class in its constructor
. This initializes the component with state
when it is created. The state
property must be set to a JavaScript object
. Declaring it looks like this:",
"this.state = {
// describe your state here
}", - "You have access to thestate
object throughout the life of your component. You can update it, render it in your UI, and pass it as props to child components. Thestate
object can be as complex or as simple as you need it to be. Note that you must create a class component by extendingReact.Component
in order to createstate
like this.", + "You have access to thestate
object throughout the life of your组件。 You can update it, render it in your UI, and pass it as props to child components. Thestate
object can be as complex or as simple as you need it to be. Note that you must create a class component by extendingReact.Component
in order to createstate
like this.", "
", "There is a component in the code editor that is trying to render aname
property from itsstate
. However, there is nostate
defined. Initialize the component withstate
in theconstructor
and assign your name to a property ofname
." ], @@ -1435,16 +1435,16 @@ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(StatefulComponent)); return mockedComponent.find('StatefulComponent').length === 1; })(), 'StatefulComponent
should exist and render.');" }, { - "text": "StatefulComponent
should render adiv
and anh1
element.", - "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(StatefulComponent)); return mockedComponent.find('div').length === 1 && mockedComponent.find('h1').length === 1; })(), 'StatefulComponent
should render adiv
and anh1
element.');" + "text": "StatefulComponent
should render adiv
and anh1
元素。", + "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(StatefulComponent)); return mockedComponent.find('div').length === 1 && mockedComponent.find('h1').length === 1; })(), 'StatefulComponent
should render adiv
and anh1
元素。');" }, { "text": "The state ofStatefulComponent
should be initialized with a propertyname
set to a string.", "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(StatefulComponent)); const initialState = mockedComponent.state(); return ( typeof initialState === 'object' && typeof initialState.name === 'string'); })(), 'The state ofStatefulComponent
should be initialized with a propertyname
set to a string.');" }, { - "text": "The propertyname
in the state ofStatefulComponent
should render in theh1
element.", - "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(StatefulComponent)); const initialState = mockedComponent.state(); return mockedComponent.find('h1').text() === initialState.name; })(), 'The propertyname
in the state ofStatefulComponent
should render in theh1
element.');" + "text": "The propertyname
in the state ofStatefulComponent
should render in theh1
元素。", + "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(StatefulComponent)); const initialState = mockedComponent.state(); return mockedComponent.find('h1').text() === initialState.name; })(), 'The propertyname
in the state ofStatefulComponent
should render in theh1
元素。');" } ], "solutions": [ @@ -1523,7 +1523,7 @@ "title": "Render State in the User Interface Another Way", "releasedOn": "December 25, 2017", "description": [ - "There is another way to accessstate
in a component. In therender()
method, before thereturn
statement, you can write JavaScript directly. For example, you could declare functions, access data fromstate
orprops
, perform computations on this data, and so on. Then, you can assign any data to variables, which you have access to in thereturn
statement.", + "There is another way to accessstate
in a组件。 In therender()
method, before thereturn
statement, you can write JavaScript directly. For example, you could declare functions, access data fromstate
orprops
, perform computations on this data, and so on. Then, you can assign any data to variables, which you have access to in thereturn
statement.", "
", "In theMyComponent
render method, define aconst
calledname
and set it equal to the name value in the component'sstate
. Because you can write JavaScript directly in this part of the code, you don't have to enclose this reference in curly braces.", "Next, in the return statement, render this value in anh1
tag using the variablename
. Remember, you need to use the JSX syntax (curly braces for JavaScript) in the return statement." @@ -1890,8 +1890,8 @@ "description": [ "Your application may have more complex interactions betweenstate
and the rendered UI. For example, form control elements for text input, such asinput
andtextarea
, maintain their own state in the DOM as the user types. With React, you can move this mutatable state into a React component'sstate
. The user's input becomes part of the applicationstate
, so React controls the value of that input field. Typically, if you have React components with input fields the user can type into, it will be a controlled input form.", "
", - "The code editor has the skeleton of a component calledControlledInput
to create a controlledinput
element. The component'sstate
is already initialized with aninput
property that holds an empty string. This value represents the text a user types into theinput
field.", - "First, create a method calledhandleChange()
that has a parameter calledevent
. When the method is called, it receives anevent
object that contains a string of text from theinput
element. You can access this string withevent.target.value
inside the method. Update theinput
property of the component'sstate
with this new string.", + "The code editor has the skeleton of a component calledControlledInput
to create a controlledinput
元素。 The component'sstate
is already initialized with aninput
property that holds an empty string. This value represents the text a user types into theinput
field.", + "First, create a method calledhandleChange()
that has a parameter calledevent
. When the method is called, it receives anevent
object that contains a string of text from theinput
元素。 You can access this string withevent.target.value
inside the method. Update theinput
property of the component'sstate
with this new string.", "In the render method, create theinput
element above theh4
tag. Add avalue
attribute which is equal to theinput
property of the component'sstate
. Then add anonChange()
event handler set to thehandleChange()
method.", "When you type in the input box, that text is processed by thehandleChange()
method, set as theinput
property in the localstate
, and rendered as the value in theinput
box on the page. The componentstate
is the single source of truth regarding the input data.", "Last but not least, don't forget to add the necessary bindings in the constructor." @@ -1960,7 +1960,7 @@ "title": "Create a Controlled Form", "releasedOn": "December 25, 2017", "description": [ - "The last challenge showed that React can control the internal state for certain elements likeinput
andtextarea
, which makes them controlled components. This applies to other form elements as well, including the regular HTMLform
element.", + "The last challenge showed that React can control the internal state for certain elements likeinput
andtextarea
, which makes them controlled components. This applies to other form elements as well, including the regular HTMLform
元素。", "
", "TheMyForm
component is set up with an emptyform
with a submit handler. The submit handler will be called when the form is submitted.", "We've added a button which submits the form. You can see it has thetype
set tosubmit
indicating it is the button controlling the form. Add theinput
element in theform
and set itsvalue
andonChange()
attributes like the last challenge. You should then complete thehandleSubmit
method so that it sets the component state propertysubmit
to the current input value in the localstate
.", @@ -2052,7 +2052,7 @@ "description": [ "You saw a lot of examples that passed props to child JSX elements and child React components in previous challenges. You may be wondering where those props come from. A common pattern is to have a stateful component containing thestate
important to your app, that then renders child components. You want these components to have access to some pieces of thatstate
, which are passed in as props.", "For example, maybe you have anApp
component that renders aNavbar
, among other components. In yourApp
, you havestate
that contains a lot of user information, but theNavbar
only needs access to the user's username so it can display it. You pass that piece ofstate
to theNavbar
component as a prop.", - "This pattern illustrates some important paradigms in React. The first is unidirectional data flow. State flows in one direction down the tree of your application's components, from the stateful parent component to child components. The child components only receive the state data they need. The second is that complex stateful apps can be broken down into just a few, or maybe a single, stateful component. The rest of your components simply receive state from the parent as props, and render a UI from that state. It begins to create a separation where state management is handled in one part of code and UI rendering in another. This principle of separating state logic from UI logic is one of React's key principles. When it's used correctly, it makes the design of complex, stateful applications much easier to manage.", + "This pattern illustrates some important paradigms in React. The first is unidirectional data flow. State flows in one direction down the tree of your application's components, from the stateful parent component to child components. The child components only receive the state data they need. The second is that complex stateful apps can be broken down into just a few, or maybe a single, stateful组件。 The rest of your components simply receive state from the parent as props, and render a UI from that state. It begins to create a separation where state management is handled in one part of code and UI rendering in another. This principle of separating state logic from UI logic is one of React's key principles. When it's used correctly, it makes the design of complex, stateful applications much easier to manage.", "
", "TheMyApp
component is stateful and renders aNavbar
component as a child. Pass thename
property in itsstate
down to the child component, then show thename
in theh1
tag that's part of theNavbar
render method." ], @@ -2123,10 +2123,10 @@ "title": "Pass a Callback as Props", "releasedOn": "December 25, 2017", "description": [ - "You can passstate
as props to child components, but you're not limited to passing data. You can also pass handler functions or any method that's defined on a React component to a child component. This is how you allow child components to interact with their parent components. You pass methods to a child just like a regular prop. It's assigned a name and you have access to that method name underthis.props
in the child component.", + "You can passstate
as props to child components, but you're not limited to passing data. You can also pass handler functions or any method that's defined on a React component to a child组件。 This is how you allow child components to interact with their parent components. You pass methods to a child just like a regular prop. It's assigned a name and you have access to that method name underthis.props
in the child组件。", "
", "There are three components outlined in the code editor. TheMyApp
component is the parent that will render theGetInput
andRenderInput
child components. Add theGetInput
component to the render method inMyApp
, then pass it a prop calledinput
assigned toinputValue
fromMyApp
'sstate
. Also create a prop calledhandleChange
and pass the input handlerhandleChange
to it.", - "Next, addRenderInput
to the render method inMyApp
, then create a prop calledinput
and pass theinputValue
fromstate
to it. Once you are finished you will be able to type in theinput
field in theGetInput
component, which then calls the handler method in its parent via props. This updates the input in thestate
of the parent, which is passed as props to both children. Observe how the data flows between the components and how the single source of truth remains thestate
of the parent component. Admittedly, this example is a bit contrived, but should serve to illustrate how data and callbacks can be passed between React components." + "Next, addRenderInput
to the render method inMyApp
, then create a prop calledinput
and pass theinputValue
fromstate
to it. Once you are finished you will be able to type in theinput
field in theGetInput
component, which then calls the handler method in its parent via props. This updates the input in thestate
of the parent, which is passed as props to both children. Observe how the data flows between the components and how the single source of truth remains thestate
of the parent组件。 Admittedly, this example is a bit contrived, but should serve to illustrate how data and callbacks can be passed between React components." ], "files": { "indexjsx": { @@ -2228,7 +2228,7 @@ "title": "Use the Lifecycle Method componentWillMount", "releasedOn": "December 25, 2017", "description": [ - "React components have several special methods that provide opportunities to perform actions at specific points in the lifecycle of a component. These are called lifecycle methods, or lifecycle hooks, and allow you to catch components at certain points in time. This can be before they are rendered, before they update, before they receive props, before they unmount, and so on. Here is a list of some of the main lifecycle methods:", + "React components have several special methods that provide opportunities to perform actions at specific points in the lifecycle of a组件。 These are called lifecycle methods, or lifecycle hooks, and allow you to catch components at certain points in time. This can be before they are rendered, before they update, before they receive props, before they unmount, and so on. Here is a list of some of the main lifecycle methods:", "componentWillMount()
", "componentDidMount()
", "componentWillReceiveProps()
", @@ -2268,8 +2268,8 @@ }, "tests": [ { - "text": "MyComponent
should render adiv
element.", - "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.find('div').length === 1; })(), 'MyComponent
should render adiv
element.');" + "text": "MyComponent
should render adiv
元素。", + "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.find('div').length === 1; })(), 'MyComponent
should render adiv
元素。');" }, { "text": "console.log
should be called incomponentWillMount
.", @@ -2289,7 +2289,7 @@ "releasedOn": "December 25, 2017", "description": [ "Most web developers, at some point, need to call an API endpoint to retrieve data. If you're working with React, it's important to know where to perform this action.", - "The best practice with React is to place API calls or any calls to your server in the lifecycle methodcomponentDidMount()
. This method is called after a component is mounted to the DOM. Any calls tosetState()
here will trigger a re-rendering of your component. When you call an API in this method, and set your state with the data that the API returns, it will automatically trigger an update once you receive the data.", + "The best practice with React is to place API calls or any calls to your server in the lifecycle methodcomponentDidMount()
. This method is called after a component is mounted to the DOM. Any calls tosetState()
here will trigger a re-rendering of your组件。 When you call an API in this method, and set your state with the data that the API returns, it will automatically trigger an update once you receive the data.", "
", "There is a mock API call incomponentDidMount()
. It sets state after 2.5 seconds to simulate calling a server to retrieve data. This example requests the current total active users for a site. In the render method, render the value ofactiveUsers
in theh1
. Watch what happens in the preview, and feel free to change the timeout to see the different effects." ], @@ -2441,7 +2441,7 @@ "Another lifecycle method iscomponentWillReceiveProps()
which is called whenever a component is receiving new props. This method receives the new props as an argument, which is usually written asnextProps
. You can use this argument and compare withthis.props
and perform actions before the component updates. For example, you may callsetState()
locally before the update is processed.", "Another method iscomponentDidUpdate()
, and is called immediately after a component re-renders. Note that rendering and mounting are considered different things in the component lifecycle. When a page first loads, all components are mounted and this is where methods likecomponentWillMount()
andcomponentDidMount()
are called. After this, as state changes, components re-render themselves. The next challenge covers this in more detail.", "
", - "The child componentDialog
receivesmessage
props from its parent, theController
component. Write thecomponentWillReceiveProps()
method in theDialog
component and have it logthis.props
andnextProps
to the console. You'll need to passnextProps
as an argument to this method and although it's possible to name it anything, name itnextProps
here.", + "The child componentDialog
receivesmessage
props from its parent, theController
组件。 Write thecomponentWillReceiveProps()
method in theDialog
component and have it logthis.props
andnextProps
to the console. You'll need to passnextProps
as an argument to this method and although it's possible to name it anything, name itnextProps
here.", "Next, addcomponentDidUpdate()
in theDialog
component, and log a statement that says the component has updated. This method works similar tocomponentWillUpdate()
, which is provided for you. Now click the button to change the message and watch your browser console. The order of the console statements show the order the methods are called.", "Note: You'll need to write the lifecycle methods as normal functions and not as arrow functions to pass the tests (there is also no advantage to writing lifecycle methods as arrow functions)." ], @@ -2526,7 +2526,7 @@ "releasedOn": "December 25, 2017", "description": [ "So far, if any component receives newstate
or newprops
, it re-renders itself and all its children. This is usually okay. But React provides a lifecycle method you can call when child components receive newstate
orprops
, and declare specifically if the components should update or not. The method isshouldComponentUpdate()
, and it takesnextProps
andnextState
as parameters.", - "This method is a useful way to optimize performance. For example, the default behavior is that your component re-renders when it receives newprops
, even if theprops
haven't changed. You can useshouldComponentUpdate()
to prevent this by comparing theprops
. The method must return aboolean
value that tells React whether or not to update the component. You can compare the current props (this.props
) to the next props (nextProps
) to determine if you need to update or not, and returntrue
orfalse
accordingly.", + "This method is a useful way to optimize performance. For example, the default behavior is that your component re-renders when it receives newprops
, even if theprops
haven't changed. You can useshouldComponentUpdate()
to prevent this by comparing theprops
. The method must return aboolean
value that tells React whether or not to update the组件。 You can compare the current props (this.props
) to the next props (nextProps
) to determine if you need to update or not, and returntrue
orfalse
accordingly.", "
", "TheshouldComponentUpdate()
method is added in a component calledOnlyEvens
. Currently, this method returnstrue
soOnlyEvens
re-renders every time it receives newprops
. Modify the method soOnlyEvens
updates only if thevalue
of its new props is even. Click theAdd
button and watch the order of events in your browser's console as the other lifecycle hooks are triggered." ], @@ -2592,8 +2592,8 @@ "testString": "assert((() => { const mockedComponent = Enzyme.mount(React.createElement(Controller)); return mockedComponent.find('Controller').length === 1 && mockedComponent.find('OnlyEvens').length === 1; })(), 'TheController
component should render theOnlyEvens
component as a child.');" }, { - "text": "TheshouldComponentUpdate
method should be defined on theOnlyEvens
component.", - "testString": "assert((() => { const child = React.createElement(OnlyEvens).type.prototype.shouldComponentUpdate.toString().replace(/s/g,''); return child !== 'undefined'; })(), 'TheshouldComponentUpdate
method should be defined on theOnlyEvens
component.');" + "text": "TheshouldComponentUpdate
method should be defined on theOnlyEvens
组件。", + "testString": "assert((() => { const child = React.createElement(OnlyEvens).type.prototype.shouldComponentUpdate.toString().replace(/s/g,''); return child !== 'undefined'; })(), 'TheshouldComponentUpdate
method should be defined on theOnlyEvens
组件。');" }, { "text": "TheOnlyEvens
component should return anh1
tag which renders the value ofthis.props.value
.", @@ -2651,8 +2651,8 @@ }, "tests": [ { - "text": "The component should render adiv
element.", - "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Colorful)); return mockedComponent.children().type() === 'div'; })(), 'The component should render adiv
element.');" + "text": "The component should render adiv
元素。", + "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Colorful)); return mockedComponent.children().type() === 'div'; })(), 'The component should render adiv
元素。');" }, { "text": "Thediv
element should have a color ofred
.", @@ -2724,8 +2724,8 @@ "testString": "assert(styles.border === \"2px solid purple\", 'Thestyles
variable should have aborder
property set to a value of2px solid purple
.');" }, { - "text": "The component should render adiv
element.", - "testString": "assert((function() { const mockedComponent = Enzyme.shallow(React.createElement(Colorful)); return mockedComponent.type() === 'div'; })(), 'The component should render adiv
element.');" + "text": "The component should render adiv
元素。", + "testString": "assert((function() { const mockedComponent = Enzyme.shallow(React.createElement(Colorful)); return mockedComponent.type() === 'div'; })(), 'The component should render adiv
元素。');" }, { "text": "Thediv
element should have its styles defined by thestyles
object.", @@ -2841,20 +2841,20 @@ "testString": "assert.strictEqual(Enzyme.mount(React.createElement(MagicEightBall)).find('MagicEightBall').length, 1, 'TheMagicEightBall
component should exist and should render to the page.');" }, { - "text": "MagicEightBall
's first child should be aninput
element.", - "testString": "assert.strictEqual(Enzyme.mount(React.createElement(MagicEightBall)).children().childAt(0).name(), 'input', 'MagicEightBall
's first child should be aninput
element.');" + "text": "MagicEightBall
's first child should be aninput
元素。", + "testString": "assert.strictEqual(Enzyme.mount(React.createElement(MagicEightBall)).children().childAt(0).name(), 'input', 'MagicEightBall
's first child should be aninput
元素。');" }, { - "text": "MagicEightBall
's third child should be abutton
element.", - "testString": "assert.strictEqual(Enzyme.mount(React.createElement(MagicEightBall)).children().childAt(2).name(), 'button', 'MagicEightBall
's third child should be abutton
element.');" + "text": "MagicEightBall
's third child should be abutton
元素。", + "testString": "assert.strictEqual(Enzyme.mount(React.createElement(MagicEightBall)).children().childAt(2).name(), 'button', 'MagicEightBall
's third child should be abutton
元素。');" }, { "text": "MagicEightBall
's state should be initialized with a property ofuserInput
and a property ofrandomIndex
both set to a value of an empty string.", "testString": "assert(Enzyme.mount(React.createElement(MagicEightBall)).state('randomIndex') === '' && Enzyme.mount(React.createElement(MagicEightBall)).state('userInput') === '', 'MagicEightBall
's state should be initialized with a property ofuserInput
and a property ofrandomIndex
both set to a value of an empty string.');" }, { - "text": "WhenMagicEightBall
is first mounted to the DOM, it should return an emptyp
element.", - "testString": "assert(Enzyme.mount(React.createElement(MagicEightBall)).find('p').length === 1 && Enzyme.mount(React.createElement(MagicEightBall)).find('p').text() === '', 'WhenMagicEightBall
is first mounted to the DOM, it should return an emptyp
element.');" + "text": "WhenMagicEightBall
is first mounted to the DOM, it should return an emptyp
元素。", + "testString": "assert(Enzyme.mount(React.createElement(MagicEightBall)).find('p').length === 1 && Enzyme.mount(React.createElement(MagicEightBall)).find('p').text() === '', 'WhenMagicEightBall
is first mounted to the DOM, it should return an emptyp
元素。');" }, { "text": "When text is entered into theinput
element and the button is clicked, theMagicEightBall
component should return ap
element that contains a random element from thepossibleAnswers
array.", @@ -2873,9 +2873,9 @@ "title": "Render with an If/Else Condition", "releasedOn": "December 25, 2017", "description": [ - "Another application of using JavaScript to control your rendered view is to tie the elements that are rendered to a condition. When the condition is true, one view renders. When it's false, it's a different view. You can do this with a standardif/else
statement in therender()
method of a React component.", + "Another application of using JavaScript to control your rendered view is to tie the elements that are rendered to a condition. When the condition is true, one view renders. When it's false, it's a different view. You can do this with a standardif/else
statement in therender()
method of a React组件。", "
", - "MyComponent contains aboolean
in its state which tracks whether you want to display some element in the UI or not. Thebutton
toggles the state of this value. Currently, it renders the same UI every time. Rewrite therender()
method with anif/else
statement so that ifdisplay
istrue
, you return the current markup. Otherwise, return the markup without theh1
element.", + "MyComponent contains aboolean
in its state which tracks whether you want to display some element in the UI or not. Thebutton
toggles the state of this value. Currently, it renders the same UI every time. Rewrite therender()
method with anif/else
statement so that ifdisplay
istrue
, you return the current markup. Otherwise, return the markup without theh1
元素。", "Note: You must write anif/else
to pass the tests. Use of the ternary operator will not pass here." ], "files": { @@ -3020,7 +3020,7 @@ "Before moving on to dynamic rendering techniques, there's one last way to use built-in JavaScript conditionals to render what you want: the ternary operator. The ternary operator is often utilized as a shortcut forif/else
statements in JavaScript. They're not quite as robust as traditionalif/else
statements, but they are very popular among React developers. One reason for this is because of how JSX is compiled,if/else
statements can't be inserted directly into JSX code. You might have noticed this a couple challenges ago — when anif/else
statement was required, it was always outside thereturn
statement. Ternary expressions can be an excellent alternative if you want to implement conditional logic within your JSX. Recall that a ternary operator has three parts, but you can combine several ternary expressions together. Here's the basic syntax:", "condition ? expressionIfTrue : expressionIfFalse", "
", - "The code editor has three constants defined within theCheckUserAge
component'srender()
method. They are calledbuttonOne
,buttonTwo
, andbuttonThree
. Each of these is assigned a simple JSX expression representing a button element. First, initialize the state ofCheckUserAge
withinput
anduserAge
both set to values of an empty string.", + "The code editor has three constants defined within theCheckUserAge
component'srender()
method. They are calledbuttonOne
,buttonTwo
, andbuttonThree
. Each of these is assigned a simple JSX expression representing a button元素。 First, initialize the state ofCheckUserAge
withinput
anduserAge
both set to values of an empty string.", "Once the component is rendering information to the page, users should have a way to interact with it. Within the component'sreturn
statement, set up a ternary expression that implements the following logic: when the page first loads, render the submit button,buttonOne
, to the page. Then, when a user enters their age and clicks the button, render a different button based on the age. If a user enters a number less than18
, renderbuttonThree
. If a user enters a number greater than or equal to18
, renderbuttonTwo
." ], "files": { @@ -3083,8 +3083,8 @@ }, "tests": [ { - "text": "TheCheckUserAge
component should render with a singleinput
element and a singlebutton
element.", - "testString": "assert(Enzyme.mount(React.createElement(CheckUserAge)).find('div').find('input').length === 1 && Enzyme.mount(React.createElement(CheckUserAge)).find('div').find('button').length === 1, 'TheCheckUserAge
component should render with a singleinput
element and a singlebutton
element.');" + "text": "TheCheckUserAge
component should render with a singleinput
element and a singlebutton
元素。", + "testString": "assert(Enzyme.mount(React.createElement(CheckUserAge)).find('div').find('input').length === 1 && Enzyme.mount(React.createElement(CheckUserAge)).find('div').find('button').length === 1, 'TheCheckUserAge
component should render with a singleinput
element and a singlebutton
元素。');" }, { "text": "TheCheckUserAge
component's state should be initialized with a property ofuserAge
and a property ofinput
, both set to a value of an empty string.", @@ -3190,12 +3190,12 @@ "testString": "assert.strictEqual(Enzyme.mount(React.createElement(GameOfChance)).find('GameOfChance').length, 1, 'TheGameOfChance
component should exist and render to the page.');" }, { - "text": "GameOfChance
should return a singlebutton
element.", - "testString": "assert.strictEqual(Enzyme.mount(React.createElement(GameOfChance)).find('button').length, 1, 'GameOfChance
should return a singlebutton
element.');" + "text": "GameOfChance
应该返回单个button
元素。", + "testString": "assert.strictEqual(Enzyme.mount(React.createElement(GameOfChance)).find('button').length, 1, 'GameOfChance
应该返回单个button
元素。');" }, { - "text": "GameOfChance
should return a single instance of theResults
component, which has a prop calledfiftyFifty
.", - "testString": "assert(Enzyme.mount(React.createElement(GameOfChance)).find('Results').length === 1 && Enzyme.mount(React.createElement(GameOfChance)).find('Results').props().hasOwnProperty('fiftyFifty') === true, 'GameOfChance
should return a single instance of theResults
component, which has a prop calledfiftyFifty
.');" + "text": "GameOfChance
应该返回单个instance of theResults
component, which has a prop calledfiftyFifty
.", + "testString": "assert(Enzyme.mount(React.createElement(GameOfChance)).find('Results').length === 1 && Enzyme.mount(React.createElement(GameOfChance)).find('Results').props().hasOwnProperty('fiftyFifty') === true, 'GameOfChance
应该返回单个instance of theResults
component, which has a prop calledfiftyFifty
.');" }, { "text": "GameOfChance
state should be initialized with a property ofcounter
set to a value of1
.", @@ -3226,7 +3226,7 @@ "title": "Change Inline CSS Conditionally Based on Component State", "releasedOn": "December 25, 2017", "description": [ - "At this point, you've seen several applications of conditional rendering and the use of inline styles. Here's one more example that combines both of these topics. You can also render CSS conditionally based on the state of a React component. To do this, you check for a condition, and if that condition is met, you modify the styles object that's assigned to the JSX elements in the render method.", + "At this point, you've seen several applications of conditional rendering and the use of inline styles. Here's one more example that combines both of these topics. You can also render CSS conditionally based on the state of a React组件。 To do this, you check for a condition, and if that condition is met, you modify the styles object that's assigned to the JSX elements in the render method.", "This paradigm is important to understand because it is a dramatic shift from the more traditional approach of applying styles by modifying DOM elements directly (which is very common with jQuery, for example). In that approach, you must keep track of when elements change and also handle the actual manipulation directly. It can become difficult to keep track of changes, potentially making your UI unpredictable. When you set a style object based on a condition, you describe how the UI should look as a function of the application's state. There is a clear flow of information that only moves in one direction. This is the preferred method when writing applications with React.", "
", "The code editor has a simple controlled input component with a styled border. You want to style this border red if the user types more than 15 characters of text in the input box. Add a condition to check for this and, if the condition is valid, set the input border style to3px solid red
. You can try it out by entering text in the input." @@ -3277,8 +3277,8 @@ }, "tests": [ { - "text": "TheGateKeeper
component should render adiv
element.", - "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(GateKeeper)); return mockedComponent.find('div').length === 1; })(), 'TheGateKeeper
component should render adiv
element.');" + "text": "TheGateKeeper
component should render adiv
元素。", + "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(GateKeeper)); return mockedComponent.find('div').length === 1; })(), 'TheGateKeeper
component should render adiv
元素。');" }, { "text": "TheGateKeeper
component should be initialized with a state keyinput
set to an empty string.", @@ -3378,12 +3378,12 @@ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find('MyToDoList').length === 1; })(), 'The MyToDoList component should exist and render to the page.');" }, { - "text": "The first child ofMyToDoList
should be atextarea
element.", - "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find('MyToDoList').children().childAt(0).type() === 'textarea'; })(), 'The first child ofMyToDoList
should be atextarea
element.');" + "text": "The first child ofMyToDoList
should be atextarea
元素。", + "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find('MyToDoList').children().childAt(0).type() === 'textarea'; })(), 'The first child ofMyToDoList
should be atextarea
元素。');" }, { - "text": "The third child ofMyToDoList
should be abutton
element.", - "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find('MyToDoList').children().childAt(2).type() === 'button'; })(), 'The third child ofMyToDoList
should be abutton
element.');" + "text": "The third child ofMyToDoList
should be abutton
元素。", + "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find('MyToDoList').children().childAt(2).type() === 'button'; })(), 'The third child ofMyToDoList
should be abutton
元素。');" }, { "text": "The state ofMyToDoList
should be initialized withtoDoList
as an empty array.", @@ -3394,8 +3394,8 @@ "testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); const initialState = mockedComponent.state(); return typeof initialState.userInput === 'string' && initialState.userInput.length === 0; })(), 'The state ofMyToDoList
should be initialized withuserInput
as an empty string.');" }, { - "text": "When theCreate List
button is clicked, theMyToDoList
component should dynamically return an unordered list that contains a list item element for every item of a comma-separated list entered into thetextarea
element.", - "testString": "async () => { const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); const simulateChange = (el, value) => el.simulate('change', {target: {value}}); const state_1 = () => { return waitForIt(() => mockedComponent.find('ul').find('li'))}; const setInput = () => { return waitForIt(() => simulateChange(mockedComponent.find('textarea'), \"testA, testB, testC\"))}; const click = () => { return waitForIt(() => mockedComponent.find('button').simulate('click'))}; const state_2 = () => { return waitForIt(() => { const nodes = mockedComponent.find('ul').find('li'); return { nodes, text: nodes.reduce((t, n) => t + n.text(), '') }; })}; const setInput_2 = () => { return waitForIt(() => simulateChange(mockedComponent.find('textarea'), \"t1, t2, t3, t4, t5, t6\"))}; const click_1 = () => { return waitForIt(() => mockedComponent.find('button').simulate('click'))}; const state_3 = () => { return waitForIt(() => { const nodes = mockedComponent.find('ul').find('li'); return { nodes, text: nodes.reduce((t, n) => t + n.text(), '') }; })}; const awaited_state_1 = await state_1(); const awaited_setInput = await setInput(); const awaited_click = await click(); const awaited_state_2 = await state_2(); const awaited_setInput_2 = await setInput_2(); const awaited_click_1 = await click_1(); const awaited_state_3 = await state_3(); assert(awaited_state_1.length === 0 && awaited_state_2.nodes.length === 3 && awaited_state_3.nodes.length === 6 && awaited_state_2.text === 'testA testB testC' && awaited_state_3.text === 't1 t2 t3 t4 t5 t6', 'When theCreate List
button is clicked, theMyToDoList
component should dynamically return an unordered list that contains a list item element for every item of a comma-separated list entered into thetextarea
element.'); }; " + "text": "When theCreate List
button is clicked, theMyToDoList
component should dynamically return an unordered list that contains a list item element for every item of a comma-separated list entered into thetextarea
元素。", + "testString": "async () => { const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); const simulateChange = (el, value) => el.simulate('change', {target: {value}}); const state_1 = () => { return waitForIt(() => mockedComponent.find('ul').find('li'))}; const setInput = () => { return waitForIt(() => simulateChange(mockedComponent.find('textarea'), \"testA, testB, testC\"))}; const click = () => { return waitForIt(() => mockedComponent.find('button').simulate('click'))}; const state_2 = () => { return waitForIt(() => { const nodes = mockedComponent.find('ul').find('li'); return { nodes, text: nodes.reduce((t, n) => t + n.text(), '') }; })}; const setInput_2 = () => { return waitForIt(() => simulateChange(mockedComponent.find('textarea'), \"t1, t2, t3, t4, t5, t6\"))}; const click_1 = () => { return waitForIt(() => mockedComponent.find('button').simulate('click'))}; const state_3 = () => { return waitForIt(() => { const nodes = mockedComponent.find('ul').find('li'); return { nodes, text: nodes.reduce((t, n) => t + n.text(), '') }; })}; const awaited_state_1 = await state_1(); const awaited_setInput = await setInput(); const awaited_click = await click(); const awaited_state_2 = await state_2(); const awaited_setInput_2 = await setInput_2(); const awaited_click_1 = await click_1(); const awaited_state_3 = await state_3(); assert(awaited_state_1.length === 0 && awaited_state_2.nodes.length === 3 && awaited_state_3.nodes.length === 6 && awaited_state_2.text === 'testA testB testC' && awaited_state_3.text === 't1 t2 t3 t4 t5 t6', 'When theCreate List
button is clicked, theMyToDoList
component should dynamically return an unordered list that contains a list item element for every item of a comma-separated list entered into thetextarea
元素。'); }; " } ], "solutions": [ @@ -3455,12 +3455,12 @@ "testString": "assert(Enzyme.mount(React.createElement(Frameworks)).find('Frameworks').length === 1, 'TheFrameworks
component should exist and render to the page.');" }, { - "text": "Frameworks
should render anh1
element.", - "testString": "assert(Enzyme.mount(React.createElement(Frameworks)).find('h1').length === 1, 'Frameworks
should render anh1
element.');" + "text": "Frameworks
should render anh1
元素。", + "testString": "assert(Enzyme.mount(React.createElement(Frameworks)).find('h1').length === 1, 'Frameworks
should render anh1
元素。');" }, { - "text": "Frameworks
should render aul
element.", - "testString": "assert(Enzyme.mount(React.createElement(Frameworks)).find('ul').length === 1, 'Frameworks
should render aul
element.');" + "text": "Frameworks
should render aul
元素。", + "testString": "assert(Enzyme.mount(React.createElement(Frameworks)).find('ul').length === 1, 'Frameworks
should render aul
元素。');" }, { "text": "Theul
tag should render 6 childli
elements.", @@ -3583,7 +3583,7 @@ "So far, you have been rendering React components on the client. Normally, this is what you will always do. However, there are some use cases where it makes sense to render a React component on the server. Since React is a JavaScript view library and you can run JavaScript on the server with Node, this is possible. In fact, React provides arenderToString()
method you can use for this purpose.", "There are two key reasons why rendering on the server may be used in a real world app. First, without doing this, your React apps would consist of a relatively empty HTML file and a large bundle of JavaScript when it's initially loaded to the browser. This may not be ideal for search engines that are trying to index the content of your pages so people can find you. If you render the initial HTML markup on the server and send this to the client, the initial page load contains all of the page's markup which can be crawled by search engines. Second, this creates a faster initial page load experience because the rendered HTML is smaller than the JavaScript code of the entire app. React will still be able to recognize your app and manage it after the initial load.", "
", - "TherenderToString()
method is provided onReactDOMServer
, which is available here as a global object. The method takes one argument which is a React element. Use this to renderApp
to a string." + "TherenderToString()
method is provided onReactDOMServer
, which is available here as a global object. The method takes one argument which is a React元素。 Use this to renderApp
to a string." ], "files": { "indexjsx": {