Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Списки: For и Index

Чтобы вывести массив — например, список задач, — в Solid используют встроенный компонент For. Он создаёт разметку для каждого элемента и при изменении массива добавляет, удаляет или переставляет только нужные узлы. Ключи, как в React, указывать не нужно.

For

// src/components/TodoList.jsx
import { createSignal, For } from 'solid-js';
 
export default function TodoList() {
  const [todos, setTodos] = createSignal([
    { id: 1, title: 'Купить молоко' },
    { id: 2, title: 'Позвонить Олегу' },
  ]);
 
  const add = () => setTodos([...todos(), { id: Date.now(), title: 'Новая задача' }]);
 
  return (
    <div>
      <ul>
        <For each={todos()}>{(todo) => <li>{todo.title}</li>}</For>
      </ul>
      <button onClick={add}>Добавить</button>
    </div>
  );
}

Выведите <TodoList /> в src/App.jsx. На странице список из двух задач, каждое нажатие добавляет ещё одну. Уже существующие li при этом не пересоздаются.

Номер элемента

Вторым аргументом функция получает номер элемента. Он может меняться при перестановках, поэтому это функция-геттер:

// src/components/TodoList.jsx
import { For } from 'solid-js';
 
export default function TodoList(props) {
  return (
    <ol>
      <For each={props.todos} fallback={<li>Задач нет</li>}>
        {(todo, index) => (
          <li>
            {index() + 1}. {todo.title}
          </li>
        )}
      </For>
    </ol>
  );
}

Использование: <TodoList todos={todos()} />. Атрибут fallback показывает «Задач нет», пока массив пуст.

Index

Index выглядит похоже, но привязывает разметку не к элементу, а к позиции в массиве:

// src/components/Scores.jsx
import { createSignal, Index } from 'solid-js';
 
export default function Scores() {
  const [scores, setScores] = createSignal([10, 20, 30]);
 
  return (
    <div>
      <Index each={scores()}>{(score, i) => <p>Место {i + 1}: {score()}</p>}</Index>
      <button onClick={() => setScores([15, 20, 30])}>Обновить</button>
    </div>
  );
}

После нажатия меняется только текст в первом абзаце. Здесь, наоборот, элемент — геттер score(), а номер i — обычное число.

Что выбрать

ForIndex
ПривязкаК элементу (объекту)К позиции
ЭлементЗначение todoГеттер score()
НомерГеттер index()Число i
Подходит дляСписков объектов: задачи, статьиПростых значений: строки, числа

В большинстве случаев нужен For.

Частая ошибка

Выводить список через map, как в React:

// src/components/TodoList.jsx
export default function TodoList(props) {
  // Работает, но при каждом изменении пересоздаёт все li
  return <ul>{props.todos.map((todo) => <li>{todo.title}</li>)}</ul>;
}

map создаёт все элементы заново при любом изменении массива: пропадает фокус в полях внутри списка, тратится лишняя работа. Используйте For.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.