Skip to content

Commit 6c5e554

Browse files
authored
docs(en): merge reactjs.org/main into zh-hans.reactjs.org/main @ 53d279e
2 parents 2fe9282 + fc9cb7c commit 6c5e554

File tree

8 files changed

+88
-33
lines changed

8 files changed

+88
-33
lines changed

beta/src/components/Icon/IconCopy.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*/
4+
5+
import * as React from 'react';
6+
7+
export const IconCopy = React.memo<JSX.IntrinsicElements['svg']>(
8+
function IconCopy({className}) {
9+
return (
10+
<svg
11+
className={className}
12+
width="1em"
13+
height="1em"
14+
viewBox="0 0 18 18"
15+
fill="none"
16+
xmlns="http://www.w3.org/2000/svg">
17+
<path
18+
fillRule="evenodd"
19+
clipRule="evenodd"
20+
d="M5.40382 15.3671C5.03332 15.1901 4.70081 14.9381 4.42481 14.6286C4.34831 14.5431 4.23931 14.5001 4.12981 14.5206L3.66181 14.6081C3.33531 14.6691 3.02032 14.4361 2.96232 14.0876L1.30981 4.12512C1.28181 3.95662 1.31731 3.7861 1.40981 3.6456C1.50231 3.5051 1.64082 3.41162 1.79932 3.38162L3.22131 3.00012C3.37681 2.97062 3.48981 2.82761 3.48981 2.65961V1.9101C3.48981 1.8276 3.49381 1.74561 3.49931 1.66461C3.50931 1.53461 3.35181 1.57211 3.35181 1.57211L1.64381 2.0076C1.18481 2.0936 0.751316 2.32662 0.451316 2.70612C0.0808162 3.17362 -0.0686885 3.77259 0.0293115 4.36459L1.68231 14.3281C1.84531 15.3081 2.65031 16.0001 3.55631 16.0001C3.66531 16.0001 3.77631 15.9896 3.88731 15.9691L5.36632 15.6916C5.52332 15.6626 5.54982 15.4366 5.40382 15.3671ZM14.9331 4.55801H12.9116C12.1351 4.55801 11.5001 3.91502 11.5001 3.12952V1.06802C11.5001 0.480524 11.0196 0 10.4321 0H7.44161C6.36911 0 5.50011 0.879508 5.50011 1.96451V12.1665C5.50011 13.179 6.33412 14 7.36262 14H14.1371C15.1661 14 16.0001 13.179 16.0001 12.1665V5.625C16.0001 5.038 15.5201 4.55801 14.9331 4.55801Z"
21+
fill="currentColor"
22+
/>{' '}
23+
<path
24+
fillRule="evenodd"
25+
clipRule="evenodd"
26+
d="M12.5888 0.0914385C12.4493 0.00843847 12.5158 0.252449 12.5158 0.252449C12.5653 0.428449 12.5918 0.613451 12.5918 0.804451V2.90296C12.5918 3.17646 12.8158 3.40046 13.0903 3.40046H15.1718C15.3883 3.40046 15.5968 3.43495 15.7918 3.49845C15.7918 3.49845 15.9373 3.50844 15.9008 3.43494C15.8383 3.33744 15.7673 3.24494 15.6833 3.16044L12.8303 0.289467C12.7558 0.214467 12.6743 0.149438 12.5888 0.0914385Z"
27+
fill="currentColor"
28+
/>
29+
</svg>
30+
);
31+
}
32+
);
33+
34+
IconCopy.displayName = 'IconCopy';

beta/src/components/MDX/Challenges/Challenges.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ export function Challenges({children, isRecipes}: ChallengesProps) {
9797
};
9898

9999
const currentChallenge = challenges.find(({id}) => id === activeChallenge);
100+
if (currentChallenge === undefined) {
101+
throw new TypeError('currentChallenge should always exist');
102+
}
100103
const nextChallenge = challenges.find(({order}) => {
101-
if (!currentChallenge) {
102-
return false;
103-
}
104104
return order === currentChallenge.order + 1;
105105
});
106106

@@ -121,7 +121,7 @@ export function Challenges({children, isRecipes}: ChallengesProps) {
121121
</H2>
122122
{challenges.length > 1 && (
123123
<Navigation
124-
activeChallenge={activeChallenge}
124+
currentChallenge={currentChallenge}
125125
challenges={challenges}
126126
handleChange={handleChallengeChange}
127127
isRecipes={isRecipes}
@@ -132,16 +132,16 @@ export function Challenges({children, isRecipes}: ChallengesProps) {
132132
<div key={activeChallenge}>
133133
<h3 className="text-xl text-primary dark:text-primary-dark mb-2">
134134
<div className="font-bold block md:inline">
135-
{isRecipes ? 'Recipe' : 'Challenge'} {currentChallenge?.order}{' '}
136-
of {challenges.length}
135+
{isRecipes ? 'Recipe' : 'Challenge'} {currentChallenge.order} of{' '}
136+
{challenges.length}
137137
<span className="text-primary dark:text-primary-dark">: </span>
138138
</div>
139-
{currentChallenge?.name}
139+
{currentChallenge.name}
140140
</h3>
141-
<>{currentChallenge?.content}</>
141+
<>{currentChallenge.content}</>
142142
</div>
143143
<div className="flex justify-between items-center mt-4">
144-
{currentChallenge?.hint ? (
144+
{currentChallenge.hint ? (
145145
<div>
146146
<Button className="mr-2" onClick={toggleHint} active={showHint}>
147147
<IconHint className="mr-1.5" />{' '}
@@ -187,14 +187,14 @@ export function Challenges({children, isRecipes}: ChallengesProps) {
187187
</Button>
188188
)}
189189
</div>
190-
{showHint && currentChallenge?.hint}
190+
{showHint && currentChallenge.hint}
191191

192192
{showSolution && (
193193
<div className="mt-6">
194194
<h3 className="text-2xl font-bold text-primary dark:text-primary-dark">
195195
Solution
196196
</h3>
197-
{currentChallenge?.solution}
197+
{currentChallenge.solution}
198198
<div className="flex justify-between items-center mt-4">
199199
<Button onClick={() => setShowSolution(false)}>
200200
Close solution

beta/src/components/MDX/Challenges/Navigation.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ const debounce = require('debounce');
1111
export function Navigation({
1212
challenges,
1313
handleChange,
14-
activeChallenge,
14+
currentChallenge,
1515
isRecipes,
1616
}: {
1717
challenges: ChallengeContents[];
1818
handleChange: (id: string) => void;
19-
activeChallenge: string;
19+
currentChallenge: ChallengeContents;
2020
isRecipes?: boolean;
2121
}) {
2222
const containerRef = React.useRef<HTMLDivElement>(null);
2323
const challengesNavRef = React.useRef(
2424
challenges.map(() => createRef<HTMLButtonElement>())
2525
);
26-
const [scrollPos, setScrollPos] = React.useState(0);
26+
const scrollPos = currentChallenge.order - 1;
2727
const canScrollLeft = scrollPos > 0;
2828
const canScrollRight = scrollPos < challenges.length - 1;
2929

@@ -37,7 +37,6 @@ export function Navigation({
3737
containerRef.current.scrollLeft = currentNavRef.offsetLeft;
3838
}
3939
handleChange(challenges[scrollPos + 1].id);
40-
setScrollPos(scrollPos + 1);
4140
}
4241
};
4342

@@ -51,7 +50,6 @@ export function Navigation({
5150
containerRef.current.scrollLeft = currentNavRef.offsetLeft;
5251
}
5352
handleChange(challenges[scrollPos - 1].id);
54-
setScrollPos(scrollPos - 1);
5553
}
5654
};
5755

@@ -64,7 +62,6 @@ export function Navigation({
6462
containerRef.current.scrollLeft = currentNavRef?.offsetLeft || 0;
6563
}
6664
handleChange(id);
67-
setScrollPos(selectedChallenge);
6865
};
6966

7067
const handleResize = React.useCallback(() => {
@@ -94,10 +91,10 @@ export function Navigation({
9491
className={cn(
9592
'py-2 mr-4 text-base border-b-4 duration-100 ease-in transition whitespace-nowrap overflow-ellipsis',
9693
isRecipes &&
97-
activeChallenge === id &&
94+
currentChallenge.id === id &&
9895
'text-purple-50 border-purple-50 hover:text-purple-50 dark:text-purple-30 dark:border-purple-30 dark:hover:text-purple-30',
9996
!isRecipes &&
100-
activeChallenge === id &&
97+
currentChallenge.id === id &&
10198
'text-link border-link hover:text-link dark:text-link-dark dark:border-link-dark dark:hover:text-link-dark'
10299
)}
103100
onClick={() => handleSelectNav(id)}

beta/src/components/MDX/TerminalBlock.tsx

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import * as React from 'react';
66
import {IconTerminal} from '../Icon/IconTerminal';
7+
import {IconCopy} from 'components/Icon/IconCopy';
78

89
type LogLevel = 'info' | 'warning' | 'error';
910

@@ -34,13 +35,36 @@ function TerminalBlock({level = 'info', children}: TerminalBlockProps) {
3435
message = children.props.children;
3536
}
3637

38+
const [copied, setCopied] = React.useState(false);
39+
React.useEffect(() => {
40+
if (!copied) {
41+
return;
42+
} else {
43+
const timer = setTimeout(() => {
44+
setCopied(false);
45+
}, 2000);
46+
return () => clearTimeout(timer);
47+
}
48+
}, [copied]);
49+
3750
return (
38-
<div
39-
className="rounded-lg bg-secondary dark:bg-gray-50 h-full"
40-
translate="no">
51+
<div className="rounded-lg bg-secondary dark:bg-gray-50 h-full">
4152
<div className="bg-gray-90 dark:bg-gray-60 w-full rounded-t-lg">
42-
<div className="text-primary-dark dark:text-primary-dark flex text-sm px-4 py-0.5 relative">
43-
<IconTerminal className="inline-flex mr-2 self-center" /> Terminal
53+
<div className="text-primary-dark dark:text-primary-dark flex text-sm px-4 py-0.5 relative justify-between">
54+
<div>
55+
<IconTerminal className="inline-flex mr-2 self-center" /> Terminal
56+
</div>
57+
<div>
58+
<button
59+
className="w-full text-left text-primary-dark dark:text-primary-dark "
60+
onClick={() => {
61+
window.navigator.clipboard.writeText(message ?? '');
62+
setCopied(true);
63+
}}>
64+
<IconCopy className="inline-flex mr-2 self-center" />{' '}
65+
{copied ? 'Copied' : 'Copy'}
66+
</button>
67+
</div>
4468
</div>
4569
</div>
4670
<div className="px-8 pt-4 pb-6 text-primary-dark dark:text-primary-dark font-mono text-code whitespace-pre">

content/docs/components-and-props.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ ReactDOM.render(
7676
);
7777
```
7878

79-
[](codepen://components-and-props/rendering-a-component)
79+
**[在 CodePen 上试试](https://codepen.io/gaearon/pen/YGYmEG?editors=1010)**
8080

8181
让我们来回顾一下这个例子中发生了什么:
8282

@@ -118,7 +118,7 @@ ReactDOM.render(
118118
);
119119
```
120120

121-
[](codepen://components-and-props/composing-components)
121+
**[在 CodePen 上试试](https://codepen.io/gaearon/pen/KgQKPr?editors=1010)**
122122

123123
通常来说,每个新的 React 应用程序的顶层组件都是 `App` 组件。但是,如果你将 React 集成到现有的应用程序中,你可能需要使用像 `Button` 这样的小组件,并自下而上地将这类组件逐步应用到视图层的每一处。
124124

@@ -152,7 +152,7 @@ function Comment(props) {
152152
}
153153
```
154154

155-
[](codepen://components-and-props/extracting-components)
155+
**[在 CodePen 上试试](https://codepen.io/gaearon/pen/VKQwEo?editors=1010)**
156156

157157
该组件用于描述一个社交媒体网站上的评论功能,它接收 `author`(对象),`text` (字符串)以及 `date`(日期)作为 props。
158158

@@ -231,7 +231,7 @@ function Comment(props) {
231231
}
232232
```
233233

234-
[](codepen://components-and-props/extracting-components-continued)
234+
**[在 CodePen 上试试](https://codepen.io/gaearon/pen/rrJNJY?editors=1010)**
235235

236236
最初看上去,提取组件可能是一件繁重的工作,但是,在大型应用中,构建可复用组件库是完全值得的。根据经验来看,如果 UI 中有一部分被多次使用(`Button``Panel``Avatar`),或者组件本身就足够复杂(`App``FeedStory``Comment`),那么它就是一个可提取出独立组件的候选项。
237237

content/docs/hello-world.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ReactDOM.render(
1717

1818
它将在页面上展示一个 "Hello, world!" 的标题。
1919

20-
[](codepen://hello-world)
20+
**[在 CodePen 上试试](https://codepen.io/gaearon/pen/rrpgNB?editors=1010)**
2121

2222
点击链接打开在线编辑器。随意更改内容,查看它们会怎样影响展示。本指南中的大多数页面都有像这样的可编辑的示例。
2323

content/docs/introducing-jsx.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ ReactDOM.render(
6868
);
6969
```
7070

71-
[](codepen://introducing-jsx)
71+
**[在 CodePen 上试试](https://codepen.io/gaearon/pen/PGEjdG?editors=1010)**
7272

7373
为了便于阅读,我们会将 JSX 拆分为多行。同时,我们建议将内容包裹在括号中,虽然这样做不是强制要求的,但是这可以避免遇到[自动插入分号](http://stackoverflow.com/q/2846283)陷阱。
7474

content/docs/rendering-elements.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const element = <h1>Hello, world</h1>;
3838

3939
`embed:rendering-elements/render-an-element.js`
4040

41-
[](codepen://rendering-elements/render-an-element)
41+
**[在 CodePen 上试试](https://codepen.io/gaearon/pen/ZpvBNJ?editors=1010)**
4242

4343
页面上会展示出 "Hello, world"。
4444

@@ -52,7 +52,7 @@ React 元素是[不可变对象](https://en.wikipedia.org/wiki/Immutable_object)
5252

5353
`embed:rendering-elements/update-rendered-element.js`
5454

55-
[](codepen://rendering-elements/update-rendered-element)
55+
**[在 CodePen 上试试](https://codepen.io/gaearon/pen/gwoJZk?editors=1010)**
5656

5757
这个例子会在 [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval) 回调函数,每秒都调用 [`ReactDOM.render()`](/docs/react-dom.html#render)
5858

@@ -66,7 +66,7 @@ React 元素是[不可变对象](https://en.wikipedia.org/wiki/Immutable_object)
6666

6767
React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。
6868

69-
你可以使用浏览器的检查元素工具查看[上一个例子](codepen://rendering-elements/update-rendered-element)来确认这一点。
69+
你可以通过查看 [上一个例子](https://codepen.io/gaearon/pen/gwoJZk?editors=1010) 来确认这一点。
7070

7171
![DOM inspector showing granular updates](../images/docs/granular-dom-updates.gif)
7272

0 commit comments

Comments
 (0)