Массивы как свойства компонентов react
Сейчас данные о пунктах списка дел хранит TodoList в свойствах label и important
const TodoList = () => (
<ul>
<li><TodoListItem label='Learn JS' important/></li>
<li><TodoListItem label='Create awesome app'/></li>
</ul>
);
Это не совсем правильный подход. Задача списка дел - отображать данные, а получать и хранить их значения и важность лучше в основном файле проекта index.js в компоненте App. При таком подходе, если нам понадобится изменить список дел, не нужно будет искать его по всем файлам проекта, достаточно будет внести изменения в основной файл.
const App = () => {
const todoDate = [
{label: 'Learn JS', important: true},
{label: 'Create awesome app', important: true},
{label: 'Drink coffee', important: false}
];
return (
<div>
<AppHeader/>
<SearchPanel/>
<TodoList todos={todoDate}/>
</div>
);
};
Мы создали массив todoDate, элементами его являются объекты с ключами label и important и добавили этот объект в качестве свойства компоненту TodoList.
Передать данные из в TodoList можно было бы так
const TodoList = ({todos}) => (
<ul>
<li><TodoListItem label={todos[0].label} important={todos[0].important}/></li>
<li><TodoListItem label={todos[1].label} important={todos[1].important}/></li>
<li><TodoListItem label={todos[2].label} important={todos[2].important}/></li>
</ul>
);
Такой подход работающий, но наивный и не оптимальный. Перебирать массив по одному элементу не совсем правильно.
Оптимизируем код выше:
const TodoList = ({todos}) => {
const elements = todos.map(item => {
return <li><TodoListItem label={item.label} important={item.important}/></li>
});
return (
<ul>
{elements}
</ul>
);
}
Можно ещё немного сократить код, использовав spread-оператор для объекта. Если имена свойств компонента совпадают с именами свойств объекта, нет необходимости перечислять их, достаточно использовать оператор расширения
В результате вот такая строка
<TodoListItem label={item.label} important={item.important}/>
превратится вот в такую
<TodoListItem {...item}/>
Этот код работает, но в консоли появились ошибки. Дело в том, что для каждого элемента списка реакт ожидает уникальный идентификатор. такой идентификатор нужен для того, чтобы, когда список изменится, реакт мог отследить изменения и обновить только изменившийся элемент, а не весь список целиком. В качестве идентификатора может использоваться порядковый номер элемента в списке, но такой подход нерациональный - дело в том, что сам реакт использует точно такой же подход и сработает он только в том случае, если новые элементы будут добавляться исключительно в конец списка.
Исправить можно так
App:
const App = () => {
const todoDate = [
{label: 'Learn JS', important: true, id: 1},
{label: 'Create awesome app', important: true, id: 2},
{label: 'Drink coffee', important: false, id: 3}
];
return (
<div>
<AppHeader/>
<SearchPanel/>
<TodoList todos={todoDate}/>
</div>
);
};
TodoList:
const TodoList = ({todos}) => {
const elements = todos.map(item => {
return (
<li key={item.id}>
<TodoListItem {...item}/>
</li>
);
});
return (
<ul>
{elements}
</ul>
);
}
Или так:
const TodoList = ({todos}) => {
const elements = todos.map(item => {
const {id, ...itemProps} = item;
return (
<li key={id}>
<TodoListItem {...itemProps}/>
</li>
);
});
return (
<ul>
{elements}
</ul>
);
}
Или так:
const TodoList = ({todos}) => {
const elements = todos.map((item, index) => {
return (
<li key={index}>
<TodoListItem {...item}/>
</li>
);
});
return (
<ul>
{elements}
</ul>
);
}