--- id: 5a24c314108439a4d4036183 title: 在 React Render 方法中使用 JavaScript challengeType: 6 forumTopicId: 301415 --- # --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); }; ``` # --solutions--