--- id: 5a24c314108439a4d403618a title: Use Array.map() to Dynamically Render Elements challengeType: 6 isRequired: false forumTopicId: 301417 localeTitle: Используйте Array.map () для динамически визуализирующих элементов --- ## Description
Условный рендеринг полезен, но вам могут понадобиться ваши компоненты для отображения неизвестного количества элементов. Часто в реактивном программировании программист не имеет никакого способа узнать, какое состояние приложения находится во время выполнения, потому что так много зависит от взаимодействия пользователя с этой программой. Программистам необходимо написать свой код для правильной обработки этого неизвестного состояния раньше времени. Использование Array.map() в React иллюстрирует это понятие. Например, вы создаете простое приложение «To Do List». Как программист, у вас нет способа узнать, сколько элементов пользователь может иметь в своем списке. Вам необходимо настроить компонент для динамического отображения правильного количества элементов списка задолго до того, как кто-то, использующий программу, решит, что сегодня день прачечной.
## Instructions
Редактор кода имеет большую часть компонента MyToDoList . Некоторые из этого кода должны выглядеть знакомыми, если вы завершили задачу контролируемой формы. Вы заметите textarea и button , а также несколько методов, которые отслеживают их состояния, но пока ничего не отображается на странице. Внутри constructor создайте объект this.state и определите два состояния: userInput должен быть инициализирован как пустая строка, а toDoList должен быть инициализирован как пустой массив. Затем удалите комментарий в методе render() рядом с переменной items . На своем месте, toDoList массив toDoList хранящийся во внутреннем состоянии компонента, и динамически визуализируйте li для каждого элемента. Попробуйте ввести строку eat, code, sleep, repeat в textarea , затем нажмите кнопку и посмотрите, что произойдет. Примечание. Возможно, вы знаете, что все дочерние элементы дочернего элемента, созданные с помощью операции сопоставления, такие как это, должны быть снабжены уникальным key атрибутом. Не беспокойтесь, это тема следующей задачи.
## Tests
```yml tests: - text: The MyToDoList component should exist and render to the page. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find('MyToDoList').length === 1; })()); - text: The first child of MyToDoList should be a textarea element. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find('MyToDoList').children().childAt(0).type() === 'textarea'; })()); - text: The third child of MyToDoList should be a button element. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); return mockedComponent.find('MyToDoList').children().childAt(2).type() === 'button'; })()); - text: The state of MyToDoList should be initialized with toDoList as an empty array. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); const initialState = mockedComponent.state(); return Array.isArray(initialState.toDoList) === true && initialState.toDoList.length === 0; })()); - text: The state of MyToDoList should be initialized with userInput as an empty string. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyToDoList)); const initialState = mockedComponent.state(); return typeof initialState.userInput === 'string' && initialState.userInput.length === 0; })()); - text: 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. 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''); }; ' ```
## Challenge Seed
```jsx const textAreaStyles = { width: 235, margin: 5 }; class MyToDoList extends React.Component { constructor(props) { super(props); // change code below this line // change code above this line this.handleSubmit = this.handleSubmit.bind(this); this.handleChange = this.handleChange.bind(this); } handleSubmit() { const itemsArray = this.state.userInput.split(','); this.setState({ toDoList: itemsArray }); } handleChange(e) { this.setState({ userInput: e.target.value }); } render() { const items = null; // change code here return (