Array.map()
说明了这个概念。例如,您创建一个简单的“待办事项列表”应用程序。作为程序员,您无法知道用户可能在其列表中有多少项。您需要设置组件,以便在使用该程序的人决定今天是洗衣日之前动态呈现正确数量的列表元素。 MyToDoList
组件。如果您完成了受控制的表单质询,那么这些代您会注意到一个textarea
和一个button
,以及一些跟踪其状态的方法,但是还没有任何内容呈现给页面。在constructor
内部,创建一个this.state
对象并定义两个状态: userInput
应初始化为空字符串, toDoList
应初始化为空数组。接下来,删除items
变量旁边的render()
方法中的注释。取而代之,映射存储在组件内部状态中的toDoList
数组,并为每个项目动态呈现li
。尝试输入字符串eat, code, sleep, repeat
到textarea
,然后单击按钮,看看会发生什么。 注意:您可能知道由这样的映射操作创建的所有兄弟子元素都需要提供唯一的key
属性。别担心,这是下一个挑战的主题。 MyToDoList
的第一个子MyToDoList
应该是textarea
元素。
testString: 'assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find("MyToDoList").children().childAt(0).type() === "textarea"; })(), "The first child of MyToDoList
should be a textarea
element.");'
- text: MyToDoList
的第三个子MyToDoList
应该是一个button
元素。
testString: 'assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find("MyToDoList").children().childAt(2).type() === "button"; })(), "The third child of MyToDoList
should be a button
element.");'
- text: 应使用toDoList
将MyToDoList
的状态初始化为空数组。
testString: 'assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); const initialState = mockedComponent.state(); return Array.isArray(initialState.toDoList) === true && initialState.toDoList.length === 0; })(), "The state of MyToDoList
should be initialized with toDoList
as an empty array.");'
- text: 应使用userInput
将MyToDoList
的状态初始化为空字符串。
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 of MyToDoList
should be initialized with userInput
as an empty string.");'
- text: 单击“ Create List
按钮时, MyToDoList
组件应动态返回无序列表,该列表包含输入到textarea
元素中的逗号分隔列表的每个项目的列表项元素。
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 the Create List
button is clicked, the MyToDoList
component should dynamically return an unordered list that contains a list item element for every item of a comma-separated list entered into the textarea
element."); }; '
```