Files
freeCodeCamp/curriculum/challenges/chinese/03-front-end-libraries/react/use-advanced-javascript-in-react-render-method.md

337 lines
8.2 KiB
Markdown
Raw Normal View History

---
id: 5a24c314108439a4d4036183
title: 在 React Render 方法中使用 JavaScript
challengeType: 6
forumTopicId: 301415
dashedName: use-advanced-javascript-in-react-render-method
---
# --description--
在之前的挑战中,你学习了如何使用大括号`{ }`将 JavaScript 代码插入到 JSX 代码中,用于访问 props、传递 props、访问 state、在代码中插入注释以及最近学习的定制组件样式等任务。这些都是将 JavaScript 放在 JSX 中的常见用例,但是在 React 组件中使用 JavaScript 代码还有其他方式。
`render`方法中编写 JavaScript你可以把 JavaScript 直接放在`return`语句之前,而***不必***将其插入大括号中。这是因为它还不在 JSX 代码中。当你稍后想在`return`语句中的 JSX 代码中使用变量时,可以将变量名放在大括号中。
# --instructions--
在提供的代码中,`render`方法中有一个包含 20 个短语的数组,用于表示 20 世纪 80 年代经典魔术八球玩具中的答案。绑定`ask`方法到按钮的单击事件,每次单击该按钮时,将生成随机数并将其存储为 state 中的`randomIndex`。在第 52 行,删除字符串`"change me!"`并重新分配`answer`常量,以便每次组件更新时,你的代码随机访问`possibleAnswers`数组的不同索引。最后,在`p`标签内插入`answer`常量。
# --hints--
`MagicEightBall`组件应该存在并被渲染到页面。
```js
assert.strictEqual(
Enzyme.mount(React.createElement(MagicEightBall)).find('MagicEightBall')
.length,
1
);
```
`MagicEightBall`的第一个子元素应该是`input`元素。
```js
assert.strictEqual(
Enzyme.mount(React.createElement(MagicEightBall))
.children()
.childAt(0)
.name(),
'input'
);
```
`MagicEightBall`的第三个子元素应该是`button`元素。
```js
assert.strictEqual(
Enzyme.mount(React.createElement(MagicEightBall))
.children()
.childAt(2)
.name(),
'button'
);
```
`MagicEightBall`的 state 应该用`userInput`属性和`randomIndex`属性初始化,并且这两个属性的值都应该是空字符串。
```js
assert(
Enzyme.mount(React.createElement(MagicEightBall)).state('randomIndex') ===
'' &&
Enzyme.mount(React.createElement(MagicEightBall)).state('userInput') === ''
);
```
`MagicEightBall`第一次加载到 DOM 中时,它应该返回一个空的`p`元素。
```js
assert(
Enzyme.mount(React.createElement(MagicEightBall)).find('p').length === 1 &&
Enzyme.mount(React.createElement(MagicEightBall)).find('p').text() === ''
);
```
当文本被输入到`input`元素中并点击按钮时,`MagicEightBall`组件应该返回一个`p`元素,该元素包含数组`possibleAnswers`中的随机一个元素。
```js
async () => {
const waitForIt = (fn) =>
new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 250));
const comp = Enzyme.mount(React.createElement(MagicEightBall));
const simulate = () => {
comp.find('input').simulate('change', { target: { value: 'test?' } });
comp.find('button').simulate('click');
};
const result = () => comp.find('p').text();
const _1 = () => {
simulate();
return waitForIt(() => result());
};
const _2 = () => {
simulate();
return waitForIt(() => result());
};
const _3 = () => {
simulate();
return waitForIt(() => result());
};
const _4 = () => {
simulate();
return waitForIt(() => result());
};
const _5 = () => {
simulate();
return waitForIt(() => result());
};
const _6 = () => {
simulate();
return waitForIt(() => result());
};
const _7 = () => {
simulate();
return waitForIt(() => result());
};
const _8 = () => {
simulate();
return waitForIt(() => result());
};
const _9 = () => {
simulate();
return waitForIt(() => result());
};
const _10 = () => {
simulate();
return waitForIt(() => result());
};
const _1_val = await _1();
const _2_val = await _2();
const _3_val = await _3();
const _4_val = await _4();
const _5_val = await _5();
const _6_val = await _6();
const _7_val = await _7();
const _8_val = await _8();
const _9_val = await _9();
const _10_val = await _10();
const actualAnswers = [
_1_val,
_2_val,
_3_val,
_4_val,
_5_val,
_6_val,
_7_val,
_8_val,
_9_val,
_10_val
];
const hasIndex = actualAnswers.filter(
(answer, i) => possibleAnswers.indexOf(answer) !== -1
);
const notAllEqual = new Set(actualAnswers);
assert(notAllEqual.size > 1 && hasIndex.length === 10);
};
```
# --seed--
## --after-user-code--
```jsx
var possibleAnswers = [
'It is certain',
'It is decidedly so',
'Without a doubt',
'Yes, definitely',
'You may rely on it',
'As I see it, yes',
'Outlook good',
'Yes',
'Signs point to yes',
'Reply hazy try again',
'Ask again later',
'Better not tell you now',
'Cannot predict now',
'Concentrate and ask again',
"Don't count on it",
'My reply is no',
'My sources say no',
'Outlook not so good',
'Very doubtful',
'Most likely'
];
ReactDOM.render(<MagicEightBall />, document.getElementById('root'));
```
## --seed-contents--
```jsx
const inputStyle = {
width: 235,
margin: 5
};
class MagicEightBall extends React.Component {
constructor(props) {
super(props);
this.state = {
userInput: '',
randomIndex: ''
};
this.ask = this.ask.bind(this);
this.handleChange = this.handleChange.bind(this);
}
ask() {
if (this.state.userInput) {
this.setState({
randomIndex: Math.floor(Math.random() * 20),
userInput: ''
});
}
}
handleChange(event) {
this.setState({
userInput: event.target.value
});
}
render() {
const possibleAnswers = [
'It is certain',
'It is decidedly so',
'Without a doubt',
'Yes, definitely',
'You may rely on it',
'As I see it, yes',
'Outlook good',
'Yes',
'Signs point to yes',
'Reply hazy try again',
'Ask again later',
'Better not tell you now',
'Cannot predict now',
'Concentrate and ask again',
"Don't count on it",
'My reply is no',
'My sources say no',
'Most likely',
'Outlook not so good',
'Very doubtful'
];
const answer = 'change me!'; // Change this line
return (
<div>
<input
type='text'
value={this.state.userInput}
onChange={this.handleChange}
style={inputStyle}
/>
<br />
<button onClick={this.ask}>Ask the Magic Eight Ball!</button>
<br />
<h3>Answer:</h3>
<p>
{/* Change code below this line */}
{/* Change code above this line */}
</p>
</div>
);
}
}
```
# --solutions--
```jsx
const inputStyle = {
width: 235,
margin: 5
};
class MagicEightBall extends React.Component {
constructor(props) {
super(props);
this.state = {
userInput: '',
randomIndex: ''
};
this.ask = this.ask.bind(this);
this.handleChange = this.handleChange.bind(this);
}
ask() {
if (this.state.userInput) {
this.setState({
randomIndex: Math.floor(Math.random() * 20),
userInput: ''
});
}
}
handleChange(event) {
this.setState({
userInput: event.target.value
});
}
render() {
const possibleAnswers = [
'It is certain',
'It is decidedly so',
'Without a doubt',
'Yes, definitely',
'You may rely on it',
'As I see it, yes',
'Outlook good',
'Yes',
'Signs point to yes',
'Reply hazy try again',
'Ask again later',
'Better not tell you now',
'Cannot predict now',
'Concentrate and ask again',
"Don't count on it",
'My reply is no',
'My sources say no',
'Outlook not so good',
'Very doubtful',
'Most likely'
];
const answer = possibleAnswers[this.state.randomIndex];
return (
<div>
<input
type='text'
value={this.state.userInput}
onChange={this.handleChange}
style={inputStyle}
/>
<br />
<button onClick={this.ask}>Ask the Magic Eight Ball!</button>
<br />
<h3>Answer:</h3>
<p>{answer}</p>
</div>
);
}
}
```