Наше приложение Bookshelf почти завершено, но мы живем в динамичном мире. Наши приложения практически никогда не бывают самодостаточными. Именно поэтому в Solid изначально заложена концепция ресурсов. Ресурсы - это специальные сигналы, разработанные специально для асинхронной загрузки и создаваемые с помощью функции createResource.
Ресурсы могут быть вызваны самими сигналами. Обычно в функцию createResource передаются два параметра: сигнал и функция извлечения данных, которая полагается на этот сигнал:
Сигнал триггерит функцию dataFetchingFunction: всякий раз, когда он становится значением, отличным от null, undefined или false, вызывается функция dataFetchingFunction с этим значением в качестве первого аргумента.
Когда наша функция dataFetchingFunction завершится, она обновит значение data(), к которому мы можем получить доступ как к обычному сигналу. Кроме того, нам будут доступны свойства data.loading и data.error, чтобы мы могли реагировать на состояние выборки данных.
В дальнейшем, если значение signal снова изменится, функция dataFetchingFunction будет запущена заново (если это значение не null, undefined или false).
В нашем приложении "Книжная полка" мы не собираемся заставлять пользователей набирать полное название и автора каждой книги: для поиска книг мы будем использовать API.
К счастью, OpenLibrary.org предоставляет API, который мы можем использовать для поиска книг по их названиям. Например, https://openlibrary.org/search.json?q=Lord%20of%20the%20Rings выполнит поиск по книге "Властелин колец", и мы сможем получить официальное название книги и ее автора.
Давайте сначала напишем функцию поиска данных searchBooks, основанную на этом API. Функция будет принимать поисковый запрос и возвращать массив совпадений из API OpenLibrary.org:
Этот код получает данные из API OpenLibrary.org, выбирает первые 10 результатов, а затем немного преобразует их, чтобы вернуть только свойства title и author для каждого результата.
Отложим на время эту функцию получения данных и займемся рефакторингом нашего компонента AddBooks.tsx. В настоящее время он состоит из формы, позволяющей пользователю ввести и название, и автора книги, которую он хочет добавить на свою книжную полку.
Теперь, когда мы знаем, что будем использовать API OpenLibrary.org, мы можем немного упростить эту форму: мы просто попросим пользователя искать книгу по ее названию. Текст, который набирает пользователь, будет задан в сигнале input. После того как пользователь нажмет кнопку Search, текущее значение сигнала input будет сохранено в сигнале query. Это будет исходный сигнал для нашего ресурса.
Теперь, когда у нас есть исходный сигнал query и функция получения данных searchBooks, мы можем использовать createResource для запроса к API OpenLibrary.org! Напомним, что createResource принимает в качестве аргументов исходный сигнал и функцию поиска данных:
1
const[data]=createResource(query,searchBooks);
Зная, что в состоянии загрузки мы будем иметь доступ к data.loading, мы можем вывести на экран "Searching...", когда данные загружаются, или список результатов, когда данные загружены. Воспользуемся изученными функциями потока управления <Show /> и <For />.
Наконец, мы хотим убедиться, что <button /> в каждом элементе списка добавляет элемент в наш список книг.
1 2 3 4 5 6 7 8 910111213141516171819202122232425
const[data]=createResource(query,searchBooks);<Showwhen={!data.loading}fallback={<>Searching...</>}><ul><Foreach={data()}>{(book)=>(<li>{book.title}by{book.author}{' '}<buttonaria-label={`Add ${book.title} by ${book.author} to the bookshelf`}onClick={(e)=>{e.preventDefault();props.setBooks((books)=>[...books,book,]);}}>Add</button></li>)}</For></ul></Show>;
Мы можем включить aria-label в нашу кнопку Add, чтобы сделать действие, выполняемое кнопкой, понятным для читателей экрана. Solid никогда не встанет на пути написания доступного кода, но он также не напишет его за вас!
import{createSignal,Setter,JSX,createResource,For,Show,}from'solid-js';import{Book}from'./App';import{searchBooks}from'./searchBooks';exportinterfaceAddBookProps{setBooks:Setter<Book[]>;}exportfunctionAddBook(props:AddBookProps){const[input,setInput]=createSignal('');const[query,setQuery]=createSignal('');const[data]=createResource<Book[],string>(query,searchBooks);return(<><form><div><labelfor="title">Searchbooks</label><inputid="title"value={input()}onInput={(e)=>{setInput(e.currentTarget.value);}}/></div><buttontype="submit"onClick={(e)=>{e.preventDefault();setQuery(input());}}>Search</button></form><Showwhen={!data.loading}fallback={<>Searching...</>}><ul><Foreach={data()}>{(book)=>(<li>{book.title}by{' '}{book.author}{' '}<buttonaria-label={`Add ${book.title} by ${book.author} to the bookshelf`}onClick={(e)=>{e.preventDefault();props.setBooks((books)=>[...books,book,]);}}>Add</button></li>)}</For></ul></Show></>);}
Вы только что создали свое первое приложение на Solid! Теперь вы знаете, как создавать пользовательские интерфейсы, управлять состоянием, условно отображать информацию и динамически получать содержимое с помощью Solid.